3

可以说,我有员工,我知道他们喜欢什么水果。

fruits(name, fruit_name)

我的问题是:列出所有至少喜欢和唐纳德一样的水果的员工。

那么如何比较两组值呢?

这就是我得到唐纳德喜欢的水果的方式:

Select name, fruit_name
from fruits
where initcap(name) like '%Donald%';

示例:唐纳德喜欢苹果、梨、桃子。我需要喜欢苹果、梨、桃子和可能其他水果的人,但他们必须喜欢这 3 个。

4

6 回答 6

2

有两种方法可以做到这一点:

使用集合

我发现这给出了最容易理解的 SQL,但它确实需要定义一个集合类型:

CREATE TYPE VARCHAR2s_Table AS TABLE OF VARCHAR2(20);

然后,您可以将所有内容分组到集合中并使用自联接并SUBMULTISET OF查找其他名称。

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';

SQLFIDDLE

或者这个的替代版本:

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 );

SQLFIDDLE

顺便说一句 - usingINITCAP(Name) LIKE '%Name%'有可能匹配多个名称,您可能会发现您正在找到几个人中的一个人喜欢的水果。

于 2013-11-06T21:10:19.967 回答
1

您可以使用自连接来获得您想要的结果-我已经稍微调整了您的查询以获得输出-

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;

上面的查询返回至少有一个水果与 Donald 匹配的员工

下面经过测试的查询提供了至少与唐纳德的所有水果相匹配的员工

     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%');
于 2013-11-06T09:22:19.463 回答
0

尝试这个:

Select distinct f2.name 
from fruits f1, fruits f2 where f1.fruit_name = f2_fruit_name 
where initcap(f1.name) like '%Donald%';
于 2013-11-06T10:02:42.390 回答
0

在 oracle plsql 中,我会使用这样的东西来打印所有喜欢唐纳德喜欢的所有水果的员工:

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
于 2013-11-06T09:43:42.103 回答
0
SELECT DISTINCT emp.name
FROM fruits emp
JOIN fruits don ON (don.fruit_name = emp.fruit_name)
WHERE INITCAP(fruits.name) LIKE '%Donald%';

这会为您提供与唐纳德至少有一种共同水果的所有员工的姓名,尽管您应该注意,您获得唐纳德喜欢的所有水果的解决方案也会为您提供说麦当劳叔叔喜欢的水果。


我看到你需要所有喜欢至少唐纳德喜欢的所有水果的人。这更难。

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
);
于 2013-11-06T09:32:10.873 回答
0
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%'
                            );
于 2013-11-06T10:17:30.470 回答