I have two tables Card
and History
with a one-to-many relationship: one card can have one or many histories. Card
has a CardId
column, and History
has a CardId
and a StatusId
column.
I want a SQL script which selects the only cards which have no one history with StatusId=310.
This is what I've tried.
SELECT
C.CardId
FROM
Card C
WHERE NOT EXISTS (SELECT *
FROM History H
WHERE H.CardId = C.CardId AND H.StatusId = 310)
But I want to know if there is an efficient way.
Thanks in advance.
To answer your question about whether there is a more efficient way:
Short answer: No, not exists
is most likely the most efficient method.
Long answer: Aaron Bertrand's article with benchmarks for many different methods of doing the same thing Should I use not in, outer apply, left outer join, except, or not exists? Spoiler: not exists
wins.
I would stick with your original code using not exists, but Aaron's article has many examples you can adapt to your situation to confirm that nothing else is more efficient.
select c.CardId
from Card c
where not exists(
select 1
from History h
where h.CardId=c.CardId
and h.StatusId=310
)
What you're after is called a "negative JOIN". Here's a version without the subquery:
SELECT c.CardId
FROM Card c
LEFT OUTER JOIN History h
ON h.CardId = c.CardId
AND h.StatusId = 310
WHERE h.CardId IS NULL;
Your NOT EXISTS
method looks reasonable but there is another approach.
SELECT *
FROM Card C
WHERE EXISTS (SELECT 1
FROM history H
WHERE H.CardId = C.CardId
HAVING Count(CASE WHEN H.StatusId = 310 THEN 1 END) = 0)
Check the performance by running both the queries with your real time data
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.