在 SQL 查询中设置差异

Posted

技术标签:

【中文标题】在 SQL 查询中设置差异【英文标题】:set difference in SQL query 【发布时间】:2010-04-01 05:26:34 【问题描述】:

我正在尝试使用语句选择记录

SELECT * 
FROM A 
WHERE 
  LEFT(B, 5) IN 
    (SELECT * FROM 
       (SELECT LEFT(A.B,5), COUNT(DISTINCT A.C) c_count 
        FROM A 
        GROUP BY LEFT(B,5)
       ) p1 
       WHERE p1.c_count = 1
     ) 
     AND C IN 
        (SELECT * FROM 
            (SELECT A.C , COUNT(DISTINCT LEFT(A.B,5)) b_count 
             FROM A 
             GROUP BY C
            ) p2 
          WHERE p2.b_count = 1)

这需要很长时间才能运行约 15 秒。

有没有更好的方法来编写这个 SQL?

【问题讨论】:

你真的必须提供带有模式的示例输入和输出数据......并接受更多答案 gbn:哈哈哈。好吧,有时有超过 1 个有效答案,我无法决定接受哪个答案。 有很多问题需要我们回答,我们可能会决定回答那些我们获得声誉和勾选框的问题 【参考方案1】:

如果您想在 SQL 中表示 Set Difference (A-B),这里有适合您的解决方案。 假设您有两个表 A 和 B,并且您想要检索仅存在于 A 中但不存在于 B 中的所有记录,其中 A 和 B 通过名为 ID 的属性建立关系。 一个有效的查询是:

# (A-B)
SELECT DISTINCT A.* FROM (A LEFT OUTER JOIN B on A.ID=B.ID) WHERE B.ID IS NULL

-来自 Jayaram Timsina 的博客。

【讨论】:

【参考方案2】:

您不需要从嵌套子查询中返回数据。我不确定这是否会在没有索引的情况下有所作为,但它更容易阅读。

在恕我直言,EXISTS/JOIN 可能比使用 IN 更好

SELECT * 
FROM
    A 
    JOIN
    (SELECT LEFT(B,5) AS b1
        FROM A 
        GROUP BY LEFT(B,5)
        HAVING COUNT(DISTINCT C) = 1
    ) t1 On LEFT(A.B, 5) = t1.b1
    JOIN
    (SELECT C AS C1
        FROM A 
        GROUP BY C
        HAVING COUNT(DISTINCT LEFT(B,5)) = 1
    ) t2 ON A.C = t2.c1

但你至少需要一个计算列,正如 marc_s 所说的那样

还有 2 个索引:一个在 (computed, C),另一个在 (C, computed)

【讨论】:

【参考方案3】:

嗯,不知道你在这里真正想要做什么 - 但很明显,LEFT(B, 5) 表达式不断弹出。由于您使用的是函数,因此您放弃了使用索引的任何机会。

您可以在 SQL Server 表中执行的操作是为该表达式创建一个计算的、持久的列,然后在其上放置一个索引:

ALTER TABLE A
   ADD LeftB5 AS LEFT(B, 5) PERSISTED

CREATE NONCLUSTERED INDEX IX_LeftB5 ON dbo.A(LeftB5)

现在在查询中的任何位置使用新的计算列 LeftB5 而不是 LEFT(B, 5) - 这应该有助于加快某些查找和 GROUP BY 操作。

另外 - 你有一个 GROUP BY C 在那里 - 列 C 有索引吗?

【讨论】:

【参考方案4】:

如果您正在寻找 table1table2 之间的差异, 下面的查询很简单,它给出了table1 中的行,而不是table2 中的行,这样两个表都是相同模式的实例,列名为 columnone, columntwo, ...

with 
col1 as (
  select columnone from table2
  ),
col2 as (
  select columntwo from table2
)
...
select * from table1
where (
  columnone not in col1 
  and columntwo not in col2
  ...
);

【讨论】:

以上是关于在 SQL 查询中设置差异的主要内容,如果未能解决你的问题,请参考以下文章

如何在 sql 中设置变量并在选择查询中使用它来显示和执行对该变量的操作(MAX MIN)?

如何在SQL查询中设置时间格式

如何在 SQL 中设置布尔值

如何在 ReDash 中设置标准 SQL BigQuery

在 Linq to SQL 查询中设置非列属性值

怎么在SQL中设置外键