So I have two tables, the first would be users_
Name
------
Carol
Sue
and the second would be interests_
Name Interest
----------------------
Carol Books
Carol Dancing
Carol Sports
Sue Books
Sue Dancing
The user will be presented with checkboxes to select a match based on criteria for similar interests like this
So if the user selected Books and Dancing as interests for their match, what type of sql query would I build to combine multiple rows in interests and ensure that the result is Sue, since she had Books and Dancing as interests but NOT Sports?
any help will go a long way thanks!
so basically to do this build a negative list of users that have more than those two and then select the others
SELECT u.name
FROM users_ u
JOIN interests_ i ON i.name = u.name
JOIN
( SELECT u.name
FROM users_ u
JOIN interests_ i ON i.name = u.name
WHERE i.interest NOT IN('Books', 'Dancing')
) t
WHERE u.name <> t.name
AND i.interest IN('Books', 'Dancing')
GROUP BY u.name
HAVING COUNT(u.name) = 2;
Here is the simple way to do it
select
i.name
from interests i
where i.interest in ('Books','Dancing')
and not exists
(
select 1 from interests i1
where interest not in ('Books','Dancing')
AND i.name = i1.name
)
group by i.name
having count(*) = 2
One way to achieve this result:
SELECT u.name
FROM users_ u
JOIN interests_ n01 ON n01.name = u.name AND n01.interest = 'Books'
JOIN interests_ n02 ON n02.name = u.name AND n02.interest = 'Dancing'
LEFT JOIN interests_ x01 ON x01.name = u.name AND x01.interest = 'Sports'
LEFT JOIN interests_ x02 ON x02.name = u.name AND x01.interest = 'Wine'
WHERE x01.name IS NULL
AND x02.name IS NULL
This approach requires a JOIN for each interest to be "included", and an anti-join to each interest to be "excluded". This approach is flexible, but can become unwieldy for a large number of interests.
To look for matches for ONLY the specified interests, without having to list out all the interests not to match, we could use an anti-join to find rows in interests that don't match:
SELECT u.name
FROM users_ u
JOIN interests_ n01 ON n01.name = u.name AND n01.interest = 'Books'
JOIN interests_ n02 ON n02.name = u.name AND n02.interest = 'Dancing'
LEFT
JOIN interests_ o
ON o.name = u.name
AND o.interest NOT IN ('Books','Dancing')
WHERE o.name IS NULL
Another approach would be to make use of JOIN operations and a COUNT()
aggregate, eg
SELECT u.name
FROM users_ u
JOIN interests_ n
ON n.name = u.name
AND n.interest IN ('Books','Dancing')
LEFT
JOIN interests_ o
ON o.name = u.name
AND o.interest NOT IN ('Books','Dancing')
WHERE o.name IS NULL
GROUP BY u.name
HAVING COUNT(DISTINCT n.interest) = 2
There are some other approaches (these are just some examples).
Make it use of SQL in
operator
select * from interests_ where Interest in ('Books', 'Dancing') and Interest not in ('Sports');
EDIT 1
This worked for me
SELECT * FROM user_ WHERE EXISTS (
SELECT i.Name, count(distinct i.Interest) FROM interests_ as i
WHERE i.Name=user_.Name
AND i.Interest IN ('Books','Dancing')
GROUP BY i.Name
HAVING count(distinct i.Interest) = 2
);
REF : SQL equivalent of IN operator that acts as AND instead of OR?
Left Joins can be very useful. You could try this.
SELECT users_.*
FROM users_
LEFT JOIN interests_
ON users_.Name = Interests_.Name
WHERE interests_.Interests = 'Books'
AND interests_.Interests = 'Dancing'
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.