Самостоятельное присоединение в PLSQL - PullRequest
0 голосов
/ 07 апреля 2011

У меня есть таблица P со столбцом personid и столбцом licensetypeid.

Каждый человек может иметь несколько типов лицензий, добавляя дополнительные строки в таблицу для этого идентификатора человека.

Мне нужно найти строки, в которых у personid есть LicenseID 1 и 5.

Я не могу написать:

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

Я слышал, что для этого нужно использовать самообъединение. Как мне самостоятельно присоединиться, чтобы решить эту проблему?

Ответы [ 5 ]

4 голосов
/ 07 апреля 2011

Самостоятельные объединения и другие способы доступа к таблице более одного раза будут работать, но могут снизить производительность и будут громоздкими, если вам нужно обобщить для больших наборов идентификаторов.

Вы можете сделать это с помощью одногоссылка на таблицу путем подсчета количества совпадающих строк на человека:

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

(вСамостоятельная версия, вам нужно будет добавить дополнительное объединение для каждого дополнительного значения)

Или если вы хотите найти людей, которые имеют как минимум 2 типа из большего набора типов:

select personid from P
  where licensetypeid in ('1','5', '7', '10')
  group by personid
  having count(*) >= 2

Теперь, в отличие от вашего примера запроса, тип лицензии не включается в набор результатов.Если это необходимо по какой-то причине, вы можете сделать простой трюк в случае 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
2 голосов
/ 07 апреля 2011
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
)
1 голос
/ 07 апреля 2011
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
;
0 голосов
/ 07 апреля 2011

Если ваш набор требуемых типов лицензий является «фиксированным», или, по крайней мере, если количество наборов требуемых типов лицензий фиксировано, данные ответы будут работать нормально.

В противном случае вам необходимонапишите 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 (...)
0 голосов
/ 07 апреля 2011

Попробуйте это

select personid,licensetypeid from P where licensetypeid in ('1','5')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...