简体   繁体   中英

sql - find items that ALL users have in common

I can find the items common between two given users similar to the answer here :

SELECT items.name 
FROM   users 
       JOIN requests 
         ON users.user_id = requests.user_id 
       JOIN items 
         ON requests.item_id = items.item_id 
WHERE  users.name = 'jane'
INTERSECT
SELECT items.name 
FROM   users 
       JOIN requests 
         ON users.user_id = requests.user_id 
       JOIN items 
         ON requests.item_id = items.item_id 
WHERE  users.name = 'zaku';

I guess I could keep adding more intersect statements to include additional users and that's hardly a good solution. How would I find any and all item(s) common among ALL users? In my eg, the common item among all users is "pc" but it could as well be any other item(s). See my code on SQL Fiddle . Thanks.

You can try something like this:

SELECT items.name 
FROM   users 
       JOIN requests 
         ON users.user_id = requests.user_id 
       JOIN items 
         ON requests.item_id = items.item_id
GROUP BY items.name
having count(items.name) = (select count(distinct user_id) from users)

The idea is to take the count of the item from your query, and to compare it to the total count of users. If its equals then it means that all users has it.

To get the items, you could simply do:

select r.item_id
from requests r
group by r.item_id
having count(distinct r.user_id) = (select count(*) from users);

Getting the name is essentially the same thing:

select i.name
from requests r join
     items i
     on r.item_id = i.item_id
group by i.name
having count(distinct r.user_id) = (select count(*) from users);

This is a similar solution as @sagi who beat me to the answer. This approach has as advantage that it can handle duplicate item_names for an user, for example, if there are two request from an user for the same item, however, this may not be applicable to your case:

SELECT  item_name
FROM    (SELECT users.name AS users_name ,
                items.name AS item_name
        FROM    users
                JOIN requests ON users.user_id = requests.user_id
                JOIN items ON requests.item_id = items.item_id
        GROUP BY users.name ,
                 items.name
        HAVING  COUNT(*) > 0
       )
GROUP BY item_name
HAVING  COUNT(*) = ( SELECT COUNT(distinct user_id) FROM   users)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM