Reputation: 51
Here is what I am trying to accomplish: 1. Pull user ID from the users table (documents.ownerID is foreign key of Users.Handle) 2. For users who do NOT have a record that was created in the documents table within the last 90 days
Here is the query that I have so far (I am running this through 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
Nothing is returned in the output. However, when I remove the "Not" from the "Not Exists" statement I get an output of users who have a record that was created in the documents table within the last 90 days. Also, if I change the ">=" indicator to "=" I receive output as well. I think the problem is that I don't have a firm understanding of the EXIST statement. I greatly appreciate your help.
Upvotes: 5
Views: 4895
Reputation: 9
Another option would be to use "except" if the table is not too big for later versions of SQL Server
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
Upvotes: 0
Reputation: 1271151
The reason is because your subquery is not correlated. So, the where
clause is saying: where no record exists in documents with a creation time greater than 90 days. There are such records, so the where
clause always fails.
My guess is that you want this by user. If so, then try this where
clause:
where not exists (select *
from documents d2
where d2.creationtime >= Dateadd(day, -90, getutcdate()) and
d2.OwnerId = users.handle
)
Upvotes: 12
Reputation: 3021
A shortcut to get the same results without using a sub-query would be to use a left join and check for NULL in the Documents table like so:
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
Upvotes: 3
Reputation: 115660
One way is to put the Documents
table inside the subquery only, removing it from the external query, so making the subquery a correlated one:
SELECT Users.UserID
FROM Users
WHERE NOT EXISTS
(
SELECT *
FROM Documents
WHERE Documents.OwnerID = Users.handle
AND Documents.creationtime >= Dateadd(day, -90, getutcdate())
) ;
This way, you can also get rid of the GROUP BY
for free.
Upvotes: 3
Reputation: 1208
If the query in your NOT EXISTS returns ANY rows you will get 0 rows back. You're saying "give me rows back if this query returns nothing"
EDIT: And yes, Gordon has the right idea below. You want to say "give me rows for THIS user if this query returns nothing for THIS user"
EDIT 2: and by below I meant above :)
Upvotes: 2