我有一个表P,带有personid列和licensetypeid列。
每个人都可以拥有多种许可证类型,并为该人员ID在表格中添加其他行。
我需要找到personid的licenseid为1和5的行。
我不能写:
SELECT personid, licensetypeid
FROM P
WHERE licensetypeid=1 AND licensetypeid=5;
我听说我应该使用自我加入来做到这一点。如何进行自我加入以解决此问题?
答案 0 :(得分:4)
自我连接和其他多次访问表的技术都可以使用,但如果你需要推广到更大的id组,可能会降低性能并且难以处理。
您可以通过计算每个人匹配的行数来对表进行一次引用:
select personid from P
where licensetypeid in ('1','5')
group by personid
having count(*) = 2
如果您想要更大的licensetypeid值,可以轻松扩展:
select personid from P
where licensetypeid in ('1','5','7')
group by personid
having count(*) = 3
(在自加入版本中,您必须为每个附加值添加额外的连接)
或者,如果您想找到一组中包含至少两种类型的人:
select personid from P
where licensetypeid in ('1','5', '7', '10')
group by personid
having count(*) >= 2
现在,与示例查询不同,licensetypeid不包含在结果集中。如果由于某种原因这是必要的,那么在2个值的情况下你可以做一个简单的技巧:
select personid, min(licensetypeid) licensetype1, max(licensetypeid) licensetype2
from P
where licensetypeid in ('1','5')
group by personid
having count(*) = 2
但更通用的方法是将值分组为一个简单的集合:
select personid, collect(licensetypeid) licensetypeidlist
from P
where licensetypeid in ('1','5')
group by personid
having count(*) = 2
答案 1 :(得分:2)
select personid, licensetypeid
from P P1
where exists (
select 1
from P P2
where P2.personid = P1.personid
and P2.licensetypeid = 1
) and exists (
select 1
from P P2
where P2.personid = P1.personid
and P2.licensetypeid = 5
)
答案 2 :(得分:1)
SELECT distinct
p1.personid
,p1.licensetypeid
,p2.licensetypeid
from P p1, P p2
WHERE p1.personid = p2.personid
AND p1.licensetypeid = 1
AND p2.licensetypeid = 5
;
答案 3 :(得分:0)
试试这个
select personid,licensetypeid from P where licensetypeid in ('1','5')
答案 4 :(得分:0)
如果您所需的许可证类型集是“固定的”,或者至少是否修复了所需许可证类型集的基数,则给定的答案将正常工作。
否则,您需要编写与所谓的“关系分区”相当的SQL。
如下:
(1)计算至少一种所需许可证类型的人员集合:
SELECT personid
from P
WHERE EXISTS
(
SELECT licenseid
from NEEDEDLICENSETYPE AS NLT
WHERE NOT EXISTS (
SELECT *
FROM P AS PBIS
WHERE
PBIS.personid = P.personid AND
PBIS.licensetype = NLT.licensetype
)
)
NEEDELICENSETYPE表示在特定调用中计算所需许可证类型集所需的任何SQL语句。
(2)选择具有未出现在(1)中的数字的人的数据:
SELECT ... FROM P WHERE personid NOT IN (...)