Lets say, I have employees, and I know what fruits they like.
fruits(name, fruit_name)
My question is: list all the employees which at least like the same fruits as Donald.
So how do I compare two set of values?
This is how I get the fruits which Donald likes:
Select name, fruit_name
from fruits
where initcap(name) like '%Donald%';
Example: Donald likes apples, pears, peaches. I need the people who like apples, pears, peaches and possibly other fruits, but they must like those 3.
You can use self join to get your desired result- I have tweaked your query a little to get the output-
select distinct e1.name from fruits e1,(Select name, fruit_name
from fruits
where initcap(name) like '%Donald%') e2
where e1.fruit_name = e2.fruit_name;
the above query returns employees for whom atleast one fruit matches with Donald
Below tested Query gives employees for whom atleast all the Donald's fruits matches
select name from (
select name,count(1) cnt from
(select name,fruit_name, case when fruit_name in (Select distinct fruit_name
from fruits
where initcap(name) like '%Donald%') then 1 else 0 end fruit_match from fruits)
where fruit_match = 1 group by name) where cnt >=
(select count(distinct fruit_name) from fruits where initcap(name) like '%Donald%');
Two ways to do this:
I find this gives the most comprehensible SQL but it does require defining a collection type:
CREATE TYPE VARCHAR2s_Table AS TABLE OF VARCHAR2(20);
Then you can just group everything up into collections and use a self join and SUBMULTISET OF
to find the other names.
WITH grouped AS (
SELECT name,
CAST( COLLECT( fruit ) AS VARCHAR2s_Table ) AS list_of_fruits
FROM fruits
GROUP BY name
)
SELECT g.name
FROM grouped f
INNER JOIN
grouped g
ON ( f.list_of_fruits SUBMULTISET OF g.list_of_fruits
AND f.name <> g.name )
WHERE f.name = 'Alice';
Or an alternative version of this:
WITH grouped AS (
SELECT name,
CAST( COLLECT( fruit ) AS VARCHAR2s_Table ) AS list_of_fruits
FROM fruits
GROUP BY name
)
SELECT name
FROM grouped
WHERE name <> 'Alice'
AND ( SELECT list_of_fruits FROM grouped WHERE name = 'Alice' )
SUBMULTISET OF list_of_fruits ;
WITH match_by_user AS (
SELECT DISTINCT
name,
fruit
FROM fruits
WHERE name = 'Alice'
)
SELECT f.name
FROM fruits f
INNER JOIN
match_by_user m
ON ( f.fruit = m.fruit
AND f.name <> m.name )
GROUP BY f.name
HAVING COUNT( DISTINCT f.fruit ) = ( SELECT COUNT(1) FROM match_by_user );
As an aside - using INITCAP(Name) LIKE '%Name%'
has the potential to match multiple names and you might find that you are finding the fruits that one of several people like.
SELECT DISTINCT emp.name
FROM fruits emp
JOIN fruits don ON (don.fruit_name = emp.fruit_name)
WHERE INITCAP(fruits.name) LIKE '%Donald%';
This gets you the names of all employees that have at least one fruit like in common with Donald, although you should note that your solution to getting all fruits Donald likes, also gives you the fruits that say, Ronald McDonald likes.
I see you need all people who like at least all fruits Donald likes. This is harder.
SELECT DISTINCT emp.name
FROM employees emp
WHERE NOT EXISTS (
SELECT *
FROM fruits don_fruits
LEFT JOIN fruits emp_fruits
ON (don_fruits.fruit_name = emp_fruits.fruit_name AND emp_fruits.name = emp.name)
WHERE INITCAP(don_fruits.name) LIKE '%Donald%'
AND emp_fruits.name IS NULL
);
In oracle plsql, I would use something like this to print all employees that like all fruits that donald likes :
declare
emp_name fruits.name%type;
begin
for rec in select distinct name from fruits
loop
select name into emp_name from
(
Select name, fruit_name
from fruits
where fruits.name=rec.name
minus
Select name, fruit_name
from fruits
where initcap(name) like '%Donald%'
)
if emp_name is null
then
dbms_output.put_line('Employee' || rec.name || 'likes same fruits as Donald');
end if
end loop
end
Try this:
Select distinct f2.name
from fruits f1, fruits f2 where f1.fruit_name = f2_fruit_name
where initcap(f1.name) like '%Donald%';
select name
from fruits
where fruit_name in (select fruit_name
from fruits
where initcap(name) like '%Donald%'
)
and initcap(name) not like '%Donald%'
group by name
having count(fruit_name) = (select count(fruit_name)
from fruits
where initcap(name) like '%Donald%'
);
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.