【问题标题】:What approach should I follow if I need to select a data 'EXCEPT' some other bunch of data?如果我需要选择一个数据“除了”其他一些数据,我应该采用什么方法?
【发布时间】:2011-12-28 23:01:57
【问题描述】:

如果我需要选择除其他数据之外的数据,我应该遵循什么方法来构建我的 SQL 查询?

例如,我的

我想从数据库中选择所有数据除了这个结果集:

SELECT *
FROM table1
WHERE table1.MarketTYpe = 'EmergingMarkets'
AND IsBigOne = 1
AND MarketVolume = 'MIDDLE'
AND SomeClass = 'ThirdClass'

我应该使用

  • NOT IN(以上结果集)
  • 或者我应该得到 INVERSE 的条件,例如 != inseat of = 等。
  • 还是?

你能建议吗?

【问题讨论】:

    标签: sql tsql filtering where-clause


    【解决方案1】:

    使用EXCEPT 构造?

    SELECT *
    FROM table1
    EXCEPT
    SELECT *
    FROM table1
    WHERE table1.MarketTYpe = 'EmergingMarkets'
    AND IsBigOne = 1
    AND MarketVolume = 'MIDDLE'
    AND SomeClass = 'ThirdClass'
    

    注意EXCEPTNOT EXISTS 使用“左反半连接”给出相同的查询计划。

    如果子查询中有 NULL 值,

    NOT IN (subquery with above) 可能不会给出正确的结果,因此我不会使用

    我会避免在 WHERE 子句中使用否定,因为它不能立即阅读
    正如迈克尔的回答中的 cmets 所示...

    有关“除某些行之外的所有行”的更多信息,请参阅以下内容:

    【讨论】:

    • 我需要关注性能吗?与使用 而不是 = 等相比?
    • @pencilcake:EXCEPT 和 NOT EXISTS 在语义上将是正确且更快的(它是查找要省略的行的半联接)。在 non-Sargable 的 WHERE 子句中也使用否定
    • +1 - SARGable 方面可能是最有说服力的论据
    【解决方案2】:

    什么数据库引擎?

    ORACLE 中的减号运算符 SQL Server 中的运算符除外

    【讨论】:

      【解决方案3】:

      这里最简单也可能最快的是简单地反转条件:

      SELECT *
      FROM table1
      WHERE table1.MarketTYpe <> 'EmergingMarkets'
        OR IsBigOne <> 1
        OR MarketVolume <> 'MIDDLE'
        OR SomeClass <> 'ThirdClass'
      

      这可能比NOT IN() 使用更少的资源。您可能希望对它们进行基准测试以确定,但上述方法可能会更快。

      【讨论】:

      • @drdwilcox 为什么?执行MarketType &lt;&gt; 'EmergingMarkets' OR IsBigOne &lt;&gt; 1 将在IsBigOne = 0 时返回MarketType = 'EmergingMarkets'。这不是我理解 OP 想要的结果的方式
      • @drdwilcox 切换到OR 将彻底改变这里的逻辑。我认为这根本不是 OP 的意图。
      • drdwilcox 是对的,您只是想要一个 4 列中的任何一个都不匹配的行(假设原始海报逻辑已正确说明,并且我们认为 OP 中的 AND 子句真正意味着 SQL AND ) deMorgans 规则将 Not thru the logic (A & B & C & D) => ! (A & B & C & D) => !A 或 !B 或 !C 或 !D
      • @Michael - 最终到达那里 :) 现在可以 +1 了 :)
      • @gbn 我有点同意。
      【解决方案4】:

      使用 NOT IN,因为这表明您希望主 select 语句中的集合不包括 NOT IN select 语句中的子集。

      【讨论】:

      • 是什么让您认为这会变慢?查询优化器可以生成相同的执行计划。您必须测试所有方法以确定哪种方法更快。
      • NOT IN 并不总是正确的,因为子查询中有 NULL 值。通常,因此应避免 NOT IN:使用 NOT EXISTS 或 EXCEPT 既正确又一致
      • 我不知道 EXCEPT ,所以学习起来很棒。但是,如果集合包含 NULL 值,我认为说 NOT IN 可能会产生 unexpected 而不是不正确的结果更准确。另见stackoverflow.com/questions/129077/…
      【解决方案5】:

      我喜欢 gbn 的回答,但另一种方法可以是:

      SELECT *
      FROM table1
      WHERE NOT (table1.MarketTYpe = 'EmergingMarkets'
      AND IsBigOne = 1
      AND MarketVolume = 'MIDDLE'
      AND SomeClass = 'ThirdClass')
      

      【讨论】:

        猜你喜欢
        • 2011-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-09
        • 2011-06-14
        • 1970-01-01
        • 2012-03-28
        • 2010-12-29
        相关资源
        最近更新 更多