Reputation: 2857
I am stuck with an this SQL problem: I need to find all members who did not pay their annual fees for 2014. Here is a sample of the database:
Table 'members'
| ID | name |
---------------
| 1 | Franck |
| 2 | Andy |
| 3 | Jack |
Table 'payements'
| ID | memberID | year | amount |
------------------------------------
| 1 | 1 | 2013 | 100 |
| 2 | 1 | 2014 | 100 |
| 3 | 2 | 2013 | 100 |
And I tried something like this:
SELECT members.name FROM members
LEFT JOIN payements ON (payements.memberID = members.ID)
WHERE (payements.year = 2014 AND payements.amount < 100) OR payements.memberID IS NULL
My query correctly finds Jack (who did never pay anything) but fails to find Andy because an entry exists for another year. How can I ask for all members who have no entry specifically for 2014 (or an entry with an amount below 100)?
Upvotes: 1
Views: 81
Reputation: 35323
Consider this data in terms of sets
We join the sets together as a left join excluding those who have paid in 2014 from the rest, we add the limits to the join so that only payments for current year in full are listed. we then exclude those from the complete set of users..
Select m.name, p.memberid, p.year, p.amount
from members m
LEFT JOIN payements p
on m.id = p.memberId
and (p.year = 2014 and p.amount >= 100)
WHERE p.year is null
The reason why your's didn't work was because the where clause was making the outer join an inner join. AND because you wanted a set of users who haven't paid. Not the set who has paid. So we needed to setup the second set as those who have paid... changing < to >=.
Upvotes: 2
Reputation: 1098
SELECT * FROM members WHERE ID NOT IN(SELECT memberID FROM payments WHERE year='2014')
Upvotes: 0
Reputation: 5436
Another way using sub-querys in WHERE
.
In the sub-query you find all members who DID pay their annual fees. So in the outer query you keep only the members not inside the sub-query, those are the ones you want.
SELECT name
FROM members
WHERE ID NOT IN (SELECT memberID
FROM payements
WHERE year = 2014 AND amount < 100)
BTW, do you mean amount <= 100
?...
EDIT: For members who paid their fees in 2014, the amount must be greater or equal than 100, so here is a corrected version:
SELECT name
FROM members
WHERE ID NOT IN (SELECT memberID
FROM payements
WHERE year = 2014 AND amount >= 100)
Added a new member "Amy" in your test, who only paid an amount of 80 in 2014, she is listed with Andy and Jack:
Andy
Jack
Amy
Upvotes: 1