【问题标题】:Most compact and efficient way to find the disunion of two sets in SQL? [duplicate]在 SQL 中找到两个集合的最紧凑和最有效的方法是什么? [复制]
【发布时间】:2018-06-01 16:58:33
【问题描述】:

举个简单的例子,假设我有两个表

  T1                      T2
=======                 =======
  Val                     Val
=======                 =======
   1                       1
   2                       3
   4                       4
   5                       5
                           6

我想要的结果集是

2
3
6

因为这些是包含在其中一个而不是另一个中的数字。我知道它可以用类似的东西来完成

WITH cte1 (Val) AS (
    SELECT Val
    FROM T1
    LEFT JOIN T2
    ON T1.Val = T2.Val
    WHERE Val IS NOT NULL
),
cte2 (Val) AS (
    SELECT Val
    FROM T2
    LEFT JOIN T1
    ON T1.Val = T2.Val
    WHERE Val IS NOT NULL
)
SELECT *
FROM cte1
UNION WITH cte2

但是有没有更紧凑和/或更有效的方法来做到这一点?

【问题讨论】:

    标签: sql sql-server tsql query-performance


    【解决方案1】:

    使用 or 子句应该可以使用完全外连接。

    SELECT isnull(t1.Val,t2.Val) [Val]
        FROM T1
        FULL OUTER JOIN T2
        ON T1.Val = T2.Val
    WHERE T1.Val is null OR T2.Val is null
    

    【讨论】:

    • 这个解决方案在性能方面似乎更好,因为大多数优化器会在后台对表进行排序,然后再关联它们。此解决方案不需要索引。点赞。
    • 优雅的解决方案。如果 OP 需要将它应用于多个列而不是两个列,我会用 COALESCE 替换 ISNULL。
    【解决方案2】:

    我会这样做:

    select t1.* 
    from t1
    where not exists (select 1 from t2 where t2.val = t1.val)
    union all
    select t2.* 
    from t2
    where not exists (select 1 from t1 where t2.val = t1.val);
    

    【讨论】:

    • 附带说明,如果您有大量数字,建议创建索引:create index ix1 on t1 (val);create index ix2 on t2 (val);
    • 这几乎就是 OP 所做的,没有 CTE 包装器。
    • @DanielE。 OP 没有使用exists
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 2011-06-04
    • 2010-12-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多