1到多个查询:帮助过滤结果

时间:2015-12-16 21:18:44

标签: sql sql-server ssms

问题:SQL查询查看"很多"中的值。关系,并没有从" 1"关系。

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

+---------------+----------------------------+-------+
| 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     |
+---------------+-------+

我希望能够运行我的查询,并能够说,&#34;当A的角色存在时,不要向我显示具有A&#34角色的唯一数字;

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

基于我的喜欢&#34;喜欢&#34;发生(我把它放在引号中,因为这甚至可能不可能)以下是我希望我的查询返回的内容。

+---------------+-------+
| 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

表格大小:这些表格可以有50,000行到500,000 +

2 个答案:

答案 0 :(得分:1)

假装表名为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');

如果子选择实际上不止一次(选择更快的那个,即子子尺寸较小的子选项),则可以是下列之一:

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]。这些方法中的任何一种都可以折叠成一个更大的查询,并且可以连接多个附加表。

[1]直接连接比涉及子选择的查询更容易阅读和执行更快,并且自引用连接的常见异常非常罕见,因为它们需要表的大小不匹配。但是,如果引用“A&#39; A”的行数,您可能会遇到这些异常。 alpha值非常小,并且索引正确。

答案 1 :(得分:0)

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

此版本使用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,其中一些可能在特定情况下具有优势。