【问题标题】:Comparing 2 Columns with Criteria in SQL在 SQL 中将 2 列与条件进行比较
【发布时间】:2022-10-04 22:24:23
【问题描述】:

我想返回给定月份中UniqReversID 不在UniqID 中的行。 我有一个查询,它给了我下面的输出。但是,运行速度非常慢。

有没有办法改变我的陈述以提高性能?

Select *  
FROM Table T1  
WHERE T1.Month = 9  
  AND T1.UniqReverseID NOT IN (  
    Select T2.UniqID  
    FROM Table T2  
    Where T2.Month = 9
  )  

桌子

UniqReverseID UniqID Month
6 2 9
-1 3 9
9 4 9
-1 5 9
2 6 9
-1 7 10
-1 8 10
4 9 10
-1 10 10

输出:

UniqReverseID UniqID Month
-1 3 9
9 4 9
-1 5 9

【问题讨论】:

    标签: sql


    【解决方案1】:

    你应该:

    • 使用索引
    • 并且尽可能用EXISTS重写IN

    上述两点,但是,尤其是关于EXISTS 的那一点会提高你的性能,因为它允许你的查询以惰性求值运行。即,一旦我们检测到第一个真假证据,我们就提前退出而无需完成评估。当您使用 IN 时,您会强制它对该子表达式进行全面评估。

    在下文中,我将您的NOT IN 改写为NOT EXISTS。 因为要搜索,所以想在NOT EXISTS做,我创建了对应的索引,保证搜索高效完成。

    -- Data
    Create Table myTable (UniqReverseID INT, UniqID INT, Month INT);
    Insert Into myTable VALUES (6, 2, 9);
    Insert Into myTable VALUES (-1, 3, 9);
    Insert Into myTable VALUES (9, 4, 9);
    Insert Into myTable VALUES (-1, 5, 9);
    Insert Into myTable VALUES (2, 6, 9);
    
    -- Indexes
    Create Index IX_myTable_001 On myTable (Month, UniqID);
    
    -- Query
    Select *
    From   myTable T1
    Where  T1.Month = 9
    And Not Exists (
            Select 1
            From   myTable T2
            Where  T2.Month  = T1.Month
            And    T2.UniqID = T1.UniqReverseID
    );
    

    我在 SQLite 中运行了上述内容。 SQLite(像许多其他数据库一样)有一个EXPLAIN QUERY PLAN,对于上面它说它使用了两次索引。一次用于 T1 搜索,再次用于 T2 搜索:

    SEARCH TABLE myTable AS T1 USING INDEX IX_myTable_001 (Month=?)
    CORRELATED SCALAR SUBQUERY 1
    SEARCH TABLE myTable AS T2 USING COVERING INDEX IX_myTable_001 (Month=? AND UniqID=?)
    

    【讨论】:

    • Sql Server 使用上述设置为 NOT IN 和 NOT EXISTS 查询生成相同的执行计划。无论如何,添加索引应该会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多