自我加入PLSQL

时间:2011-04-07 11:28:14

标签: sql oracle self-join

我有一个表P,带有personid列和licensetypeid列。

每个人都可以拥有多种许可证类型,并为该人员ID在表格中添加其他行。

我需要找到personid的licenseid为1和5的行。

我不能写:

SELECT personid, licensetypeid 
FROM P 
WHERE licensetypeid=1 AND licensetypeid=5;

我听说我应该使用自我加入来做到这一点。如何进行自我加入以解决此问题?

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 (...)