SQL的“Where Not Exists”没有返回任何行

5
以下是我想要实现的内容: 1. 从用户表中获取用户ID(documents.ownerID 是 Users.Handle 的外键) 2. 对于在过去90天内没有在documents表中创建记录的用户
以下是我目前使用的查询语句(我正在通过 SQL Studio Management 2012 运行):
Select Users.UserID 
From Documents  
Inner Join Users on documents.OwnerID = users.handle
Where Not Exists
(
Select * 
From Documents
Where documents.creationtime >= Dateadd(day, -90, getutcdate())
)
Group by Users.UserID
Order by Users.UserID ASC

输出中没有任何内容。但是,当我从“Not Exists”语句中删除“Not”时,我会得到一个输出,其中包含在过去90天内在文档表中创建记录的用户。此外,如果我将“>=”指示器更改为“=” ,我也会收到输出。我认为问题在于我对EXIST语句的理解还不够充分。非常感谢您的帮助。

5个回答

11

原因是因为你的子查询没有相关性。因此,where子句是在说:在文档中不存在创作时间大于90天的记录。这样的记录是存在的,所以where子句总是失败。

我猜你想按用户查找。如果是这样,请尝试使用以下where子句:

where not exists (select *
                  from documents d2
                  where d2.creationtime >= Dateadd(day, -90, getutcdate()) and
                        d2.OwnerId = users.handle
                 )

EXISTS语句是其中一个有趣的语句,它实际上可以引用括号外的数据集。这是允许的原因之一,是为了能够将其与另一个数据集相关联。 - coge.soft

3

一种方法是将Documents表格仅放在子查询中,从外部查询中删除它,使子查询成为一个相关的查询:

SELECT Users.UserID 
FROM Users 
WHERE NOT EXISTS
    (
    SELECT * 
    FROM Documents
    WHERE Documents.OwnerID = Users.handle
      AND Documents.creationtime >= Dateadd(day, -90, getutcdate())
    ) ;

通过这种方式,您也可以免费摆脱GROUP BY


3

不使用子查询获得相同结果的快捷方式是使用左连接,并在Documents表中检查NULL,如下所示:

SELECT Users.UserID
FROM Users  
LEFT JOIN Documents on documents.OwnerID = users.handle
    AND documents.creationtime >= Dateadd(day, -90, getutcdate())
WHERE Documents.OwnerID IS NULL
ORDER BY Users.UserID ASC

2
如果您的NOT EXISTS查询返回任何行,您将得到0行返回。您的意思是“如果此查询未返回任何内容,请给我返回行”。编辑:是的,Gordon在下面的想法是正确的。您要说“如果此用户的查询未返回此用户的任何内容,请给我返回此用户的行”。编辑2:我是指上面的下面 :)

我对“不存在(Not Exists)”的理解是,查询将返回所有未包含在子查询中的内容,这正确吗?因此,如果用户在90天内没有创建记录,则他们将在我的特定查询中返回(当然,在Gordon提出的编辑之后),对吗?感谢您的帮助。 - user2124571
通常情况下,您希望将NOT EXISTS子查询连接到主查询中。因此,在您的原始查询中,您是在说“如果在过去90天内的文档中没有行,则获取我的记录”。而在Gordon的查询中,他是在说“获取所有用户没有相关文档的记录,这些文档来自过去90天”。希望这可以帮助您。 - Aushin

0

另一个选择是,如果表不太大,则可以在SQL Server的后续版本中使用"except"

SELECT Users.UserID FROM Documents INNER JOIN Users ON documents.OwnerID = users.handle WHERE documents.creationtime >= Dateadd(day, - 90, getutcdate()) GROUP BY Users.UserID

EXCEPT

( SELECT * FROM Documents WHERE documents.creationtime >= Dateadd(day, - 90, getutcdate()) ) ORDER BY Users.UserID ASC


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接