Объединение ГДЕ СУЩЕСТВУЕТ и IN в SQL - PullRequest
0 голосов
/ 07 марта 2019

Учтите, что в таблице n строк с ИМЯ и специальностью.

NAME SPECIALITY
AA     X
AA     Y
BB     X
CC     X
CC     Y
CC     Z

Мне потребовались имена, специальность которых включала X и Y. В результате я должен получить AA и CC.Я сталкиваюсь с тем, где существует, но пока не могу правильно его оформить:

SELECT DISTINCT NAME
FROM SAMPLE
WHERE EXISTS (
    SELECT SPECIALITY
    FROM SAMPLE
    WHERE SPECIALITY IN ('X','Y')
);

В результате отображаются все имена.Я не мог взломать это правильно.Не могли бы вы помочь понять?

Ответы [ 6 ]

1 голос
/ 07 марта 2019

Вы можете использовать EXISTS следующим образом:

SELECT name
FROM sample AS tx
WHERE speciality = 'x'
AND EXISTS (
    SELECT 1
    FROM sample AS ty
    WHERE ty.name = tx.name
    AND ty.speciality = 'y'
)

Он найдет все x строки, в которых существует строка y.

1 голос
/ 07 марта 2019

Вы можете сделать простое self join для таблицы, чтобы получить желаемый результат, как показано ниже.

SELECT t1.NAME 
FROM   yourtable t1 
       INNER JOIN yourtable t2 
               ON t1.NAME = t2.NAME 
WHERE  t1.speciality = 'x' 
       AND t2.speciality = 'y' 

Приведенный выше запрос покажет все names, имеющие speciality x и y.

1 голос
/ 07 марта 2019

Вы можете использовать self join, как показано ниже:

select distinct t1.NAME from SAMPLE t1 join SAMPLE t2
on t1.NAME = t2.NAME 
and t1.SPECIALITY = 'X' and t2.SPECIALITY = 'Y'
1 голос
/ 07 марта 2019

используйте агрегацию

select name 
from tab
where SPECIALITY in ('X','Y')
group by name
having count(distinct SPECIALITY)=2

и по вашему запросу я могу редактировать, как показано ниже

SELECT DISTINCT NAME
FROM SAMPLE t1
WHERE EXISTS (SELECT SPECIALITY  FROM 
             SAMPLE t2
             WHERE SPECIALITY IN ('X','Y') and
             t1.NAME=t2.NAME 
             having count(distinct SPECIALITY)=2
            );
0 голосов
/ 07 марта 2019

Требуемый вам оператор связи известен как деление a.k.a. поставщик, который поставляет все детали.

В SQL нет оператора деления, поэтому вы должны свернуть свой собственный, в зависимости от того, хотите ли вы точные или остатки и т. Д.

Но если у вас когда-нибудь будет только два жестко закодированных значения, вы можете упростить задачу:

SELECT NAME FROM SAMPLE WHERE SPECIALITY IN = 'X'
INTERSECT
SELECT NAME FROM SAMPLE WHERE SPECIALITY IN = 'Y'
0 голосов
/ 07 марта 2019

EXISTS версия требует двух EXISTS:

SELECT S.*
FROM SAMPLE S
WHERE EXISTS (SELECT 1 FROM SAMPLE S1 WHERE S.NAME = S1.NAME AND S1.SPECIALITY = 'X') AND
      EXISTS (SELECT 1 FROM SAMPLE S1 WHERE S.NAME = S1.NAME AND S1.SPECIALITY = 'Y');

Однако, простая агрегация также должна работать:

SELECT S.NAME
FROM SAMPLE S
WHERE SPECIALITY IN ('X', 'Y')
GROUP BY NAME
HAVING MIN(SPECIALITY) <> MAX(SPECIALITY);
...