How do I select all the lifters who have never done running and swimming?
activity_log
| user | week no. | activity |
|---|---|---|
| a | 2 | swimming |
| a | 2 | lifting |
| b | 2 | lifting |
| a | 2 | lifting |
| d | 2 | lifting |
| c | 2 | running |
| b | 3 | climbing |
| c | 3 | running |
| a | 3 | lifting |
SELECT a.user
FROM activity_log a
WHERE a.activity = 'lifting' AND a.user NOT IN (
SELECT DISTINCT b.user
FROM activity_log b
WHERE b.activity IN ('running', 'swimming'))
so far here is my take but is there a better way for this?
CodePudding user response:
Do a GROUP BY. Use the HAVING clause to avoid runners and swimmers.
SELECT a.user
FROM activity_log a
GROUP BY a.user
HAVING SUM(when A.activity IN ('running', 'swimming') then 1 else 0 end) = 0
Alternatively, use EXCEPT:
SELECT a.user FROM activity_log a
EXCEPT
SELECT a.user FROM activity_log a WHERE A.activity IN ('running', 'swimming')
(The GROUP BY query will probably perform better.)
CodePudding user response:
Of course there is a bit faster way to do it.
You can use JOIN instead of WHERE as JOINS are faster than WHERE. Here is how you query may look:
SELECT a.user
FROM activity_log a
LEFT JOIN
(
SELECT DISTINCT b.user
FROM activity_log b
WHERE b.activity IN ('running', 'swimming')
) as c
ON a.user=c.user
WHERE a.activity = 'lifting' AND c.user IS NULL
As you might know, while using LEFT JOIN, we get NULL for user if they don't have activity as running or swimming. Hence taking IS NULL to filter.
