Ste*_*SQL 11 sql t-sql sql-server
有两组员工:经理和咕噜声.
对于每个经理,都有一个表manager_meetings,其中包含每个经理参加的会议列表.类似的表grunt_meetings包含每个grunt参加的会议的列表.
所以:
manager_meetings grunt_meetings
managerID meetingID gruntID meetingID
1 a 4 a
1 b 4 b
1 c 4 c
2 a 4 d
2 b 5 a
3 c 5 b
3 d 5 c
3 e 6 a
6 c
7 b
7 a
Run Code Online (Sandbox Code Playgroud)
当经理和咕噜声知道完全相同的信息时,所有者不喜欢它.这让他头痛.他想确定这种情况,因此他可以将经理降级为咕噜声,或者将咕噜声推向经理,或者让他们两人打高尔夫球.主人喜欢打高尔夫球.
任务是列出经理和咕噜声的每个组合,其中两者都参加了完全相同的会议.如果经理参加的会议多于咕噜声,那就没有比赛.如果咕噜声参加了比经理更多的会议,没有比赛.
这里的预期结果是:
ManagerID GruntID
2 7
1 5
Run Code Online (Sandbox Code Playgroud)
...因为经理2和咕噜7都参加了(a,b),而经理1和咕噜5都参加了(a,b,c).
我可以通过将子查询中的会议子集转换为XML,并将每个grunt的XML列表与每个管理器的XML进行比较,以笨重的方式解决它.但这太可怕了,我还要向所有者解释XML是什么.而且我不喜欢打高尔夫球.
有没有更好的方法"WHERE {subset1} = {subset2}"呢?感觉我错过了一些聪明的加入.
这是一个有效的版本:
select m.mId, g.gId, count(*) --select m.mid, g.gid, mm.meetingid, gm.meetingid as gmm
from manager m cross join
grunt g left outer join
(select mm.*, count(*) over (partition by mm.mid) as cnt
from manager_meeting mm
) mm
on mm.mid = m.mId full outer join
(select gm.*, count(*) over (partition by gm.gid) as cnt
from grunt_meeting gm
) gm
on gm.gid = g.gid and gm.meetingid = mm.meetingid
group by m.mId, g.gId, mm.cnt, gm.cnt
having count(*) = mm.cnt and mm.cnt = gm.cnt;
Run Code Online (Sandbox Code Playgroud)
字符串比较方法更短,可能更容易理解,并且可能更快.
编辑:
对于获取完全匹配的特定情况,可以简化查询:
select mm.mId, gm.gId
from (select mm.*, count(*) over (partition by mm.mid) as cnt
from manager_meeting mm
) mm join
(select gm.*, count(*) over (partition by gm.gid) as cnt
from grunt_meeting gm
) gm
on gm.meetingid = mm.meetingid and
mm.cnt = gm.cnt
group by mm.mId, gm.gId
having count(*) = max(mm.cnt);
Run Code Online (Sandbox Code Playgroud)
在性能和清晰度方面,这可能与字符串版本更具竞争力.
它计算了grunt和manager之间的匹配数.然后它会检查这是每个会议的所有会议.
| 归档时间: |
|
| 查看次数: |
800 次 |
| 最近记录: |