一对多查询:帮助筛选结果

1 to Many Query: Help Filtering Results

问题:SQL 查询查看 "Many" 关系中的值,而不是 return 来自“1”关系的值。

Tables 示例:(这显示了两个不同的表)。

+---------------+----------------------------+-------+
| Unique Number | <-- Table 1 -- Table 2 --> | Roles |
+---------------+----------------------------+-------+
|             1 |                            | A     |
|             2 |                            | B     |
|             3 |                            | C     |
|             4 |                            | D     |
|             5 |                            |       |
|             6 |                            |       |
|             7 |                            |       |
|             8 |                            |       |
|             9 |                            |       |
|            10 |                            |       |
+---------------+----------------------------+-------+

当我 运行 我的查询时,我得到多个唯一的数字,这些数字显示与每个数字相关联的所有角色。

+---------------+-------+
| Unique Number | Roles |
+---------------+-------+
|             1 | C     |
|             1 | D     |
|             2 | A     |
|             2 | B     |
|             3 | A     |
|             3 | B     |
|             4 | C     |
|             4 | A     |
|             5 | B     |
|             5 | C     |
|             5 | D     |
|             6 | D     |
|             6 | A     |
+---------------+-------+

我希望能够 运行 我的查询并且能够说 "When the role of A is present, don't even show me the unique numbers that have the role of A"。

也许如果 SQL 可以查看角色并说,当角色 A 出现时,获取唯一编号并将其从第 1 列中删除。

基于我希望 "like" 发生的事情(我把它放在引号中,因为这甚至可能是不可能的)以下是我希望我对 return.[=14 的查询=]

+---------------+-------+
| Unique Number | Roles |
+---------------+-------+
|             1 | C     |
|             1 | D     |
|             5 | B     |
|             5 | C     |
|             5 | D     |
+---------------+-------+

更新:

查询示例:我正在查询 8 个表,但为了简单起见,我将其压缩为 4 个。

SELECT
c.UniqueNumber,
cp.pType,
p.pRole,
a.aRole

FROM c

JOIN cp ON cp.uniqueVal = c.uniqueVal
JOIN p  ON p.uniqueVal = cp.uniqueVal
LEFT OUTER JOIN a.uniqueVal = p.uniqueVal

WHERE
--I do some basic filtering to get to the relevant clients data but nothing more than that.

ORDER BY
c.uniqueNumber

Table 大小: 这些表的行数从 50,000 到 500,000+

有很多方法可以做到,权衡取舍取决于所涉及的 table 的大小以及可用的索引等因素。根据一般原则,我的第一直觉是避免相关子查询,例如提出的另一个现已删除的答案,但如果关系 table 很小,那么它可能并不重要。

此版本改为在 where 子句中使用 un 相关子查询,并结合 not in 运算符:

select num, role
from one_to_many
where num not in (select otm2.num from one_to_many otm2 where otm2.role = 'A')

如果 one_to_many 中有很多行,该表格可能特别有效,但只有一小部分起作用 A。当然,如果返回结果行的顺序很重要,您可以添加 order by 子句。

还有一些替代方案涉及加入内联视图或 CTE,其中一些在特定情况下可能具有优势。

假装 table 名称是 t 并且列名称是 alphanumb:

SELECT t.numb, t.alpha 
FROM t 
LEFT JOIN t AS s ON t.numb = s.numb 
      AND s.alpha = 'A' 
WHERE s.numb IS NULL;

您还可以进行子选择:

SELECT numb, alpha 
FROM t 
WHERE numb NOT IN (SELECT numb FROM t WHERE alpha = 'A');

或者如果子选择不止一次具体化,则执行以下操作之一(选择速度更快的,即子table 大小较小的那个):

SELECT t.numb, t.alpha 
FROM t 
JOIN (SELECT numb FROM t GROUP BY numb HAVING SUM(alpha = 'A') = 0) AS s USING (numb);

SELECT t.numb, t.alpha 
FROM t 
LEFT JOIN (SELECT numb FROM t GROUP BY numb HAVING SUM(alpha = 'A') > 0) AS s USING (numb) 
WHERE s.numb IS NULL;

但第一个可能更快更好[1]。这些方法中的任何一种都可以折叠成一个更大的查询,并加入多个额外的 tables。

[1] 与涉及子选择的查询相比,直接连接往往更易于阅读且执行速度更快,并且自引用连接的常见异常极为罕见,因为它们需要 table秒。但是,如果引用 'A' alpha 值的行数非常小并且索引正确,则您可能会遇到这些异常。