【问题标题】:Finding pairs that share commonalities in ORACLE DB在 ORACLE DB 中查找具有共同点的对
【发布时间】:2021-09-15 02:20:24
【问题描述】:

所以我目前正在努力完成上述任务(大学作业)。

我需要找到一对拥有相同喜爱的鸡尾酒并且至少参加过一次相同活动的人 (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 方法也是如此。

我确信这个问题有一个优雅的解决方案。从某种意义上说,我的方法更像是“蛮力”。

我们将不胜感激!

【问题讨论】:

  • JOINJOINJOIN从不FROM 子句中使用逗号。
  • 除了使用过时的隐式连接语法而不是使用显式的join 子句之外,我认为您的解决方案没有问题。它实际上会产生错误的结果吗?
  • 样本数据会有很大帮助。
  • @GordonLinoff 我从不喜欢使用逗号分隔来构建笛卡尔积,因为它会产生如此多的冗余数据集,但这就是我们在 Uni 中学习的方式,但感谢您的回答我不认识您可以像这样使用 JOIN

标签: sql database oracle relational-database


【解决方案1】:

为了简单起见(以及我稍后将发布的 CTE 中的示例数据,因为您没有提供任何数据),我正在创建一个简单的视图,用于连接人们和他们访问过的地方(将 VID 更改为em>可读):

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 2019-04-01
    • 1970-01-01
    相关资源
    最近更新 更多