【问题标题】:Select No Rows If Any Row Meets A Condition?如果任何行满足条件,请选择无行?
【发布时间】:2015-07-23 23:09:44
【问题描述】:

如果结果集中的任何行满足特定条件,如何不选择任何行?

例如:

Id|SomeColumn|Indicator
1 | test     | Y
1 | test1    | Y
1 | test2    | X
2 | test1    | Y
2 | test2    | Y
3 | test1    | Y

假设我想选择 Id = 1 的所有行,除非存在指示符 = X 的行

目前我正在做这样的事情

SELECT * FROM SOMETABLE WHERE ID = 1 AND INDICATOR = 'Y' AND ID NOT IN (SELECT ID WHERE INDICATOR = 'X')

但这感觉真的很笨拙,我觉得可能有更好的方法来做到这一点。是否存在或者我只是过于敏感

【问题讨论】:

  • 您可以将INDICATOR = 'Y' 排除在WHERE 之外,否则也可以。

标签: sql tsql


【解决方案1】:

这样的?

SELECT * 
FROM SOMETABLE 
WHERE ID = 1 
AND NOT EXISTS (SELECT 1 FROM SOMETABLE WHERE INDICATOR = 'X')

或者,如果您希望 X 仅区分相同的 id:

SELECT * 
FROM SOMETABLE t1
WHERE t1.ID = 1 
AND NOT EXISTS (SELECT 1 FROM SOMETABLE t2 WHERE t1.ID = t1.ID AND INDICATOR = 'X')

【讨论】:

  • 我喜欢 NOT EXISTS 它可能是语法糖,但看起来更干净
【解决方案2】:

没有太多的选择可以做到这一点。另一种选择是使用EXISTS。

SELECT * 
FROM SOMETABLE s1 
WHERE ID = 1 AND INDICATOR = 'Y' 
     AND NOT EXISTS (SELECT TOP 1 ID FROM SOMETABLE s2 WHERE s1.ID = s2.ID AND INDICATOR = 'X')

【讨论】:

    【解决方案3】:

    另一种选择,假设指标列中有强制订单。

    DECLARE @T TABLE
        (
          ID INT
        , someColumn VARCHAR(5)
        , Indicator CHAR(1)
        )
    INSERT  INTO @T
            ( ID, someColumn, Indicator )
    VALUES  ( 1, 'test', 'Y' ),
            ( 1, 'test1', 'Y' ),
            ( 1, 'test2', 'X' ),
            ( 2, 'test1', 'Y' ),
            ( 2, 'test2', 'Y' ),
            ( 3, 'test1', 'Y' )
    
    SELECT t.ID
           , t.someColumn
           , t.Indicator
    FROM @T t
        JOIN (SELECT ID
                FROM @T t2
                GROUP BY t2.ID
                HAVING MIN(indicator) >= 'Y') q ON q.ID = t.ID
    

    不确定它是否不那么笨重,但它可能会表现得更好,因为它使用的是正排除而不是负排除。

    【讨论】:

      猜你喜欢
      • 2017-01-13
      • 1970-01-01
      • 2019-04-24
      • 1970-01-01
      • 2011-07-20
      • 2017-11-15
      • 1970-01-01
      • 2013-04-08
      相关资源
      最近更新 更多