SQL查找一起参加会议最多的两个人
Posted
技术标签:
【中文标题】SQL查找一起参加会议最多的两个人【英文标题】:SQL to find two people who participated in the most meetings together 【发布时间】:2021-03-16 06:54:27 【问题描述】:我有如下三张表:
由此我得找出一起参加会议最多的两个人。
【问题讨论】:
这里的大多数人希望样本表数据和预期结果为格式化文本,而不是图像(或图像链接)。还向我们展示您当前的查询尝试。 minimal reproducible example 此截屏直接来自在线代码测试,违反了您在测试开始时达成的协议 【参考方案1】:这只是一个自我加入会议:
select top (1) with ties p1.person_id, p2.person_id,
count(*) as num_meetings
from participant p1 join
participant p2
on p1.meeting_id = p2.meeting_id
group by p1.person_id, p2.person_id
order by count(*) desc;
这会返回人员 ID,这会回答您的问题。如果您想了解有关person
表中人员的更多信息,则可以将此类信息加入其中。
【讨论】:
【参考方案2】:这应该能让你继续前进。
样本数据
create table person
(
id int,
name nvarchar(10)
);
insert into person (id, name) values
(1, 'Alice'),
(2, 'Bob'),
(3, 'Charlie'),
(4, 'David'),
(5, 'Eric');
create table meeting
(
id int,
title nvarchar(30)
);
insert into meeting (id, title) values
(100, 'Corporate training'),
(200, 'Weekly sales'),
(300, 'Welcome introduction'),
(400, 'Evaluation');
create table participant
(
idMeeting int,
idPerson int
);
insert into participant (idMeeting, idPerson) values
(100,1), (100,2), (100,3), (100,4), (100,5),
(200,1), (200,2),
(300,2), (300,3), (300,4),
(400,3), (400,5),
(500,3), (500,5);
解决方案
通过加入具有相同会议 ID (pa2.idMeeting = pa1.idMeeting
) 的参与者行来查找共享会议。
select me.title,
pe1.name,
pe2.name
from participant pa1
join participant pa2
on pa2.idMeeting = pa1.idMeeting
and pa2.idPerson <> pa1.idPerson
join meeting me
on me.id = pa1.idMeeting
join person pe1
on pe1.id = pa1.idPerson
join person pe2
on pe2.id = pa2.idPerson;
这将为您提供许多重复项,例如 Alice
转到 Corporate training
和 Bob
和 Bob
转到 Corporate training
和 Alice
。这些当然是相同的情况。我们可以通过说参与者不仅必须不同(pa2.idPerson <> pa1.idPerson
),还必须“排序”(pa2.idPerson > pa1.idPerson
)来过滤重复。
select me.title,
pe1.name,
pe2.name
from participant pa1
join participant pa2
on pa2.idMeeting = pa1.idMeeting
and pa2.idPerson > pa1.idPerson
join meeting me
on me.id = pa1.idMeeting
join person pe1
on pe1.id = pa1.idPerson
join person pe2
on pe2.id = pa2.idPerson;
这为您提供了所有会议的所有独特组合。会议详细信息可以从结果中排除(删除join meeting
)。对唯一组合 (group by pe1.name, pe2.name
) 进行分组会给出一个计数 (count(1) as SharedMeetings
)。
select pe1.name as Person1,
pe2.name as Person2,
count(1) as SharedMeetings
from participant pa1
join participant pa2
on pa2.idMeeting = pa1.idMeeting
and pa2.idPerson > pa1.idPerson
join person pe1
on pe1.id = pa1.idPerson
join person pe2
on pe2.id = pa2.idPerson
group by pe1.name,
pe2.name
order by SharedMeetings desc,
pe1.name,
pe2.name;
结果
对于最终查询:
Person1 Person2 SharedMeetings
------- ------- --------------
Charlie Eric 3
Alice Bob 2
Bob Charlie 2
Bob David 2
Charlie David 2
Alice Charlie 1
Alice David 1
Alice Eric 1
Bob Eric 1
David Eric 1
Fiddle 查看实际情况(中间版本)。
【讨论】:
【参考方案3】:SELECT TOP(1)
partnerA.person_id,
partnerB.person_id,
(
SELECT COUNT(*)
FROM meeting
WHERE EXISTS(SELECT 1 FROM participant WHERE participant.meeting_id = meeting.meeting_id AND participant.person_id = partnerA.person_id)
AND EXISTS(SELECT 1 FROM participant WHERE participant.meeting_id = meeting.meeting_id AND participant.person_id = partnerB.person_id)
) AS participated_together
FROM person partnerA
CROSS JOIN person partnerB
WHERE partnerA.person_id < partnerB.person_id
ORDER BY participated_together DESC
这仅显示 1 对与大多数会议一起,
但您可以更改它以显示更多 - 只需更改 TOP(1)
【讨论】:
【参考方案4】:这是为了防止多对人参加相同的最大会议次数
with t1 as (select a.person_id, b.person_id, count(*) as cnt
from meetings a join meetings b
on a.meeting_id = b.meeting_id
and a.person_id < b.person_id
group by 1, 2)
select concat(a.first_name, ' ', a.last_name) as person1,
concat(b.first_name, ' ', b.last_name) as person2
from t1 join person a
on t1.person_id = a.person_id
join person b
on t1.person_id = b.person_id
where cnt = (select max(cnt) from t1)
【讨论】:
【参考方案5】:给你:
WITH OUTE AS
(SELECT CONCAT(D.FIRST_NAME,' ',D.LAST_NAME) FIRST_PERSON,
CONCAT(E.FIRST_NAME,' ',E.LAST_NAME) SECOND_PERSON,
C.TITLE
FROM PARTICIPANT A
JOIN PARTICIPANT B
ON A.MEETING_ID=B.MEETING_ID
AND A.PERSON_ID !=B.PERSON_ID
AND A.PERSON_ID < B.PERSON_ID
JOIN PERSON D
ON A.PERSON_ID=D.PERSON_ID
JOIN PERSON E
ON B.PERSON_ID=E.PERSON_ID
JOIN MEETING C
ON A.MEETING_ID=C.MEETING_ID
),
OUTE2 AS
(SELECT FIRST_PERSON,
SECOND_PERSON,
COUNT(*) MEETINGS
FROM OUTE
GROUP BY FIRST_PERSON,
SECOND_PERSON)
,
OUTE3 AS
(SELECT X.FIRST_PERSON,
X.SECOND_PERSON,
X.TITLE,
Y.MEETINGS
FROM OUTE X
JOIN OUTE2 Y
ON X.FIRST_PERSON=Y.FIRST_PERSON
AND X.SECOND_PERSON=Y.SECOND_PERSON
ORDER BY Y.MEETINGS DESC)
SELECT FIRST_PERSON,
SECOND_PERSON,
TITLE
FROM OUTE3
WHERE MEETINGS = (SELECT MEETINGS FROM OUTE3 LIMIT 1)
ORDER BY TITLE;
解决方案有待改进。
【讨论】:
欢迎来到 SO。在大多数情况下,纯代码答案缺乏解释;考虑解释这如何回答问题,以便为未来的其他用户增加价值。 @ConnorLow,感谢您的评论。我将在下一次编辑中添加完整的解释。以上是关于SQL查找一起参加会议最多的两个人的主要内容,如果未能解决你的问题,请参考以下文章
查询 CSV::Table 以在普通的旧 ruby 脚本中查找两个给定日期之间销售额最多的项目