MS SQL On使用WHERE EXISTS和WHERE NOT EXISTS

时间:2014-04-27 15:22:48

标签: sql sql-server

我在同一个查询中使用EXISTS而不是EXISTS,但没有得到任何结果。我正在寻找具有特定位置和子位置的结果,但是想要排除该特定位置存在的项目,但是该子位置为空。我是新手,所以我可能在这里遗漏了一些东西。这是我的疑问:

    SELECT a.*
    FROM dbo.table AS a
    WHERE EXISTS (SELECT Distinct b.EventID
                FROM dbo.table AS b
                WHERE b.EventID = a.EventID
                AND b.Position = 'ABC' 
                AND b.SubPosition = 'DEF') 

    AND NOT EXISTS (SELECT Distinct b.EventID
                FROM  dbo.table AS b
                WHERE b.EventID = a.EventID
                AND  b.Position = 'ABC'
                AND  b.SubPosition IS NULL)

THX。

3 个答案:

答案 0 :(得分:1)

EXCEPT可替代同一查询中的EXISTSNOT EXISTS

 SELECT * FROM Test T
  WHERE T.EventId IN
   (
     SELECT EventId FROM Test T WHERE T.Position = 'ABC' AND T.SubPosition = 'DEF'
     EXCEPT
     SELECT EventId FROM Test T WHERE T.Position = 'ABC' AND T.SubPosition IS NULL
   )

EXCEPT会产生不同的行。

答案 1 :(得分:0)

首先,您的英语语言描述不清楚,与SQL不匹配。如果你在看 “..对于有特定位置和子位置的结果,......”

然后你只需写

SELECT * FROM dbo.table a
Where Position = 'ABC' 
   AND SubPosition = 'DEF'

显然,这些行都没有空子位置......

所以我假设你打算写: “查找那些eventId的所有行的结果,其中有一个具有特定位置和子位置的eventId的行,....”

然后,从结果集中,您希望排除那些具有null SubPosition的行? 如果这是准确的,那么试试这个:

SELECT * FROM dbo.table a
WHERE EXISTS 
    (SELECT * FROM dbo.table 
     WHERE EventID = a.EventID
        AND Position = 'ABC' 
        AND SubPosition = 'DEF') 
   AND SubPosition IS NULL

另一种编写方法是使用IN运算符(在这种情况下,子查询不相关,因此您不需要任何别名):

SELECT * FROM dbo.table
WHERE EventID In 
    (SELECT EventID 
     FROM dbo.table 
     WHERE Position = 'ABC' 
        AND SubPosition = 'DEF') 
  AND SubPosition IS NULL

编辑:    在你的评论之后,我猜你的意思实际上是:
查找那些eventIds的所有行的结果,其中对于具有特定位置和子位置的eventId存在一行,但是不存在具有该位置和空子位置的任何行。”这不同于从输出中消除具有Null子位置的行!这会消除EventIds的行,其中表中的任何行都带有null子位置。这是你想要的吗?如果是的话,

然后试试这个:

SELECT * FROM dbo.table a
WHERE EXISTS 
    (SELECT * FROM dbo.table 
     WHERE EventID = a.EventID
        AND Position = 'ABC' 
        AND SubPosition = 'DEF') 
   AND Not EXISTS 
    (SELECT * FROM dbo.table 
     WHERE EventID = a.EventID
        AND Position = 'ABC' 
        AND SubPosition IS NULL) 

好的,试试这些问题并告诉我你得到了什么

     SELECT * FROM dbo.table 
     WHERE EventID = 2
        AND Position = 'ABC' 
        AND SubPosition = 'DEF' -- should return one row

和...

     SELECT * FROM dbo.table 
     WHERE EventID = 2
        AND Position = 'ABC' 
        AND SubPosition IS NULL -- should return NO rows

如果这是真的,那么主查询也应该返回EventId = 2

的一行

FURTHUR编辑:

执行此操作以创建包含测试数据的测试表并执行查询:

CREATE TABLE [dbo].[TEST](
[EventId] [int] NULL,
[Pos] [char](3) NULL,
[subPos] [char](3) NULL
)

Insert Test(EventId, Pos, SubPos) Values (1, 'ABC', 'DEF')
Insert Test(EventId, Pos, SubPos) Values (1, 'ABC', null)
Insert Test(EventId, Pos, SubPos) Values (2, 'ABC', 'DEF')
Insert Test(EventId, Pos, SubPos) Values (3, 'ABC', 'DEF')
Insert Test(EventId, Pos, SubPos) Values (3, 'ABC', null)

SELECT * FROM dbo.test a
WHERE EXISTS 
    (SELECT * FROM dbo.test 
     WHERE EventID = a.EventID
       AND Pos = 'ABC' 
       AND SubPos = 'DEF') 
  AND Not EXISTS 
    (SELECT * FROM dbo.test 
     WHERE EventID = a.EventID
       AND Pos = 'ABC' 
       AND SubPos IS NULL) 

顺便说一句,除非需要从查询的那一部分外部引用该表/结果集,否则不需要表或结果集的别名。查询中唯一的位置是主表,需要从两个相关的子查询中引用。 任何内容都不会引用相关的子查询。

答案 2 :(得分:0)

我们来看

的示例数据
1, ABC, DEF
2, ABC, NULL
3, ABC, IFG

第一个子查询只匹配1,因此EXISTS返回true。

第二个子查询将匹配1和3,因此NOT EXISTS返回false。

所以查询简化为:SELECT * FROM dbo.table WHERE 1 AND 0,它不返回任何记录。

我认为你可以从dbo.table WHERE Position ='ABC'和SubPosition ='DEF'做SELECT *来获得你想要的记录,即Position是ABC,SubPosition是DEF。如果你想要一个特定的SubPosition,那么整个“不是空”部分是没有意义的,所以也许这个问题需要重新思考......?

阅读完所有评论后编辑:

啊,现在我得到了你想要的东西(也许):

SELECT * FROM dbo.table a 
WHERE a.Position = 'ABC' AND 
     a.SubPosition='DEF' AND 
     NOT EXISTS(SELECT * FROM dbo.Table 
                  WHERE a.EventID = EventID AND 
                        a.Position = Position AND 
                        SubPosition = NULL)