在 ORACLE DB 中查找具有共同点的对
Finding pairs that share commonalities in ORACLE DB
所以我目前正在努力完成上述任务(大学作业)。
我需要找到两人 (p1.LASTNAME,p2.LASTNAME) 都喜欢同样的鸡尾酒并且至少参加过一次相同的活动。
所需的 Oracle 表是 PERSON 和 VISITED,它们如下所示:
CREATE TABLE PERSON
(
PID INT,
FIRSTNAME VARCHAR2(255) NOT NULL,
LASTNAME VARCHAR2(255) NOT NULL,
FAVCOCKTAIL INT,
PRIMARY KEY (PID),
FOREIGN KEY (FAVCOCKTAIL) REFERENCES COCKTAIL (CID)
);
CREATE TABLE VISITED
(
PID INT,
VID INT,
FOREIGN KEY (PID) REFERENCES PERSON (PID),
FOREIGN KEY (VID) REFERENCES VISITED (VID)
);
到目前为止,这是我的方法:
SELECT DISTINCT P1.LASTNAME, P2.LASTNAME, B1.VID, B2.VID, P1.FAVCOCKTAIL, P2.FAVCOCKTAIL
FROM PERSON P1,
PERSON P2,
VISITED B1,
VISITED B2
WHERE P1.FAVCOCKTAIL = P2.FAVCOCKTAIL
AND B1.VID = B2.VID
AND P1.LASTNAME != P2.LASTNAME;
现在每当我读到“至少一次”时,我都在考虑使用我尝试过的 COUNT 函数,但我无法让它工作,我尝试过的几个 JOIN 方法也是如此。
我确信这个问题有一个优雅的解决方案。我的方法在某种意义上更像是“蛮力”。
不胜感激!
为了简单起见(CTE 中的样本数据我稍后会 post,因为你没有提供任何数据),我正在创建一个简单的视图,将他们访问过的人和地方连接起来(将 VID 更改为 可读):
create or replace view v_view as
select p.pid, p.lastname, p.favcocktail, v.vid
from person p join visited v on v.pid = p.pid;
那么,如果你这样做,你可能会得到结果:
SQL> with v_view (pid, lastname, favcocktail, vid) as
2 (select 1, 'Scott', 'Pepsi', 'London' from dual union all
3 select 2, 'King' , 'Pepsi', 'London' from dual union all
4 select 3, 'Mike' , '7up' , 'London' from dual union all
5 select 4, 'John' , 'Pepsi', 'Paris' from dual
6 )
7 select listagg(a.lastname, ', ') within group (order by null) people,
8 a.favcocktail,
9 a.visited
10 from v_view a join v_view b on a.pid <> b.pid
11 and a.favcocktail = b.favcocktail
12 and a.vid = b.vid
13 group by a.favcocktail,
14 a.visited;
PEOPLE FAVCOCKTAIL VID
------------------------------ --------------- ---------------
King, Scott Pepsi London
SQL>
或者,不将示例数据和视图移入 CTE(以便您可以立即执行):
with v_view as
(select p.pid, p.lastname, p.favcocktail, v.vid
from person p join visited v on v.pid = p.pid
)
select listagg(a.lastname, ', ') within group (order by null) people,
a.favcocktail,
a.vid
from v_view a join v_view b on a.pid <> b.pid
and a.favcocktail = b.favcocktail
and a.vid = b.vid
group by a.favcocktail,
a.vid;
所以我目前正在努力完成上述任务(大学作业)。
我需要找到两人 (p1.LASTNAME,p2.LASTNAME) 都喜欢同样的鸡尾酒并且至少参加过一次相同的活动。
所需的 Oracle 表是 PERSON 和 VISITED,它们如下所示:
CREATE TABLE PERSON
(
PID INT,
FIRSTNAME VARCHAR2(255) NOT NULL,
LASTNAME VARCHAR2(255) NOT NULL,
FAVCOCKTAIL INT,
PRIMARY KEY (PID),
FOREIGN KEY (FAVCOCKTAIL) REFERENCES COCKTAIL (CID)
);
CREATE TABLE VISITED
(
PID INT,
VID INT,
FOREIGN KEY (PID) REFERENCES PERSON (PID),
FOREIGN KEY (VID) REFERENCES VISITED (VID)
);
到目前为止,这是我的方法:
SELECT DISTINCT P1.LASTNAME, P2.LASTNAME, B1.VID, B2.VID, P1.FAVCOCKTAIL, P2.FAVCOCKTAIL
FROM PERSON P1,
PERSON P2,
VISITED B1,
VISITED B2
WHERE P1.FAVCOCKTAIL = P2.FAVCOCKTAIL
AND B1.VID = B2.VID
AND P1.LASTNAME != P2.LASTNAME;
现在每当我读到“至少一次”时,我都在考虑使用我尝试过的 COUNT 函数,但我无法让它工作,我尝试过的几个 JOIN 方法也是如此。
我确信这个问题有一个优雅的解决方案。我的方法在某种意义上更像是“蛮力”。
不胜感激!
为了简单起见(CTE 中的样本数据我稍后会 post,因为你没有提供任何数据),我正在创建一个简单的视图,将他们访问过的人和地方连接起来(将 VID 更改为 可读):
create or replace view v_view as
select p.pid, p.lastname, p.favcocktail, v.vid
from person p join visited v on v.pid = p.pid;
那么,如果你这样做,你可能会得到结果:
SQL> with v_view (pid, lastname, favcocktail, vid) as
2 (select 1, 'Scott', 'Pepsi', 'London' from dual union all
3 select 2, 'King' , 'Pepsi', 'London' from dual union all
4 select 3, 'Mike' , '7up' , 'London' from dual union all
5 select 4, 'John' , 'Pepsi', 'Paris' from dual
6 )
7 select listagg(a.lastname, ', ') within group (order by null) people,
8 a.favcocktail,
9 a.visited
10 from v_view a join v_view b on a.pid <> b.pid
11 and a.favcocktail = b.favcocktail
12 and a.vid = b.vid
13 group by a.favcocktail,
14 a.visited;
PEOPLE FAVCOCKTAIL VID
------------------------------ --------------- ---------------
King, Scott Pepsi London
SQL>
或者,不将示例数据和视图移入 CTE(以便您可以立即执行):
with v_view as
(select p.pid, p.lastname, p.favcocktail, v.vid
from person p join visited v on v.pid = p.pid
)
select listagg(a.lastname, ', ') within group (order by null) people,
a.favcocktail,
a.vid
from v_view a join v_view b on a.pid <> b.pid
and a.favcocktail = b.favcocktail
and a.vid = b.vid
group by a.favcocktail,
a.vid;