Reputation: 3282
I know, this question was askes some more times but I just cant get it.
The important columns:
Saved Data:
Every name is stored multiple times even with the same category like:
name | category | date
-----|----------|-------
jeff | exCat | 2015-07-02
paul | red | 2015-07-04
jeff | red | 2015-07-03
paul | blue | ...
kevin| green | ...
jeff | green | ...
mike | red
In this case >> Exclude jeff and output all others.
The Goal:
Select all names in between two dates not having a specific category (called "exCat" here) anywhere in this timespan.
Sounds easy doesnt it? Well, cant get it anyway. The first part is easy:
SELECT name FROM myTable WHERE date >= @start AND date <= @end
(Could use BETWEEN
too).
Then I would need something like WHERE category NOT LIKE "exCat"
.
This wont work. This query would output me everyone who got at least one other category beside "exCat". But I need the guys not even one time containing "exCat" in this specific timespan.
One possible thing:
SELECT
name AS Name
FROM myTable
WHERE date >= @start AND
date <= @end AND
Name NOT IN (SELECT
name
FROM myTable
WHERE date >= @start AND
date <= @end AND
category LIKE "exCat")
GROUP BY name
So this would be just like SELECT name WHERE name NOT IN (SELECT name WHO GOT AT LEAST 1 "exCat")
Like this I would exclude only people who got at least one "exCat" e.g. I would get a result with people not having "exCat" anywhere.
The problem with that: Every subquery needs about 0.05 seconds, both together like this about 15 minutes. Thats too much.
Upvotes: 0
Views: 41
Reputation: 2153
Try this
SELECT name
FROM mytable
GROUP BY name
HAVING NOT FIND_IN_SET('exCat', GROUP_CONCAT(category))
Upvotes: 0
Reputation: 72175
You can use conditional aggregation:
SELECT name
FROM mytable
GROUP BY name
HAVING COUNT(CASE WHEN category = 'exCat' THEN 1 END) = 0
This is a way of excluding only people who got at least one exCat
without using a sub-query.
Upvotes: 1