Многократное сравнение (ANY, ALL)

Проверка на существование (EXISTS)

Проверка на принадлежность результатам вложенного запроса

Значение некоторого выражения проверяется на равенство одному из множества значений, возвращенных вложенным запросом. Эта проверка напоминает простую проверку на членство в множестве. Вложенный запрос может возвращать не более одного столбца.

Синтаксис:

<выражение> [NOT] IN (<вложенный запрос>)

 

Пример 46. Вывести список мелодий, уже назначенных какому-либо контакту.

SELECT NAZV

FROM MELODII

WHERE ID IN (SELECT DISTINCT MEL_ID FROM KONTAKTY)

 

Вариант без вложенного запроса:

SELECT DISTINCT M.NAZV

FROM MELODII M, KONTAKTY K

WHERE M.ID=K.MEL_ID

 

Пример 47. Вывести список мелодий, назначавшихся только для групп контактов.

SELECT NAZV

FROM MELODII

WHERE (ID IN (SELECT DISTINCT MEL_ID FROM GRUPPY)) AND

(ID NOT IN (SELECT DISTINCT MEL_ID FROM KONTAKTY))

 

С помощью такого условия проверяется наличие (или отсутствие) строк в таблице результатов вложенного запроса, который обязательно должен содержать внешнюю ссылку, т.е. столбец из таблицы главного запроса.

Синтаксис:

[NOT] EXISTS (<связанный вложенный запрос>)

Условие EXISTS считается выполненным, если подзапрос вернул хотя бы одну строку не важно каких данных.

Условие NOT EXISTS считается выполненным, если подзапрос не вернул ни одной строки.

Проверка на существование не использует результаты вложенного запроса, а проверяет только их наличие. По этой причине в SQL смягчается правило, согласно которому «вложенный запрос должен возвращать один столбец данных», поэтому на практике при записи вложенного запроса в проверке EXISTS всегда используется форма SELECT *.

 

Пример 48. Вывести список контактов, уже отнесенных к какой-либо группе.

SELECT K.NAME1

FROM KONTAKTY K

WHERE EXISTS (SELECT * FROM KONT_GR WHERE KONT_ID=K.ID)

 

Вариант без вложенного запроса:

SELECT DISTINCT K.NAME1

FROM KONTAKTY K, KONT_GR KG

WHERE KONT_ID=K.ID

 

Пример 49. Вывести список контактов, не отнесенных ни к одной группе.

SELECT K.NAME1

FROM KONTAKTY K

WHERE NOT EXISTS (SELECT * FROM KONT_GR KG WHERE KG.KONT_ID=K.ID)

 

Вариант с проверкой на принадлежность результатам вложенного запроса:

SELECT NAME1

FROM KONTAKTY

WHERE ID NOT IN (SELECT DISTINCT KONT_ID FROM KONT_GR)

 

Вариант без вложенного запроса:

SELECT K.NAME1

FROM KONTAKTY K LEFT JOIN KONT_GR KG ON KG.KONT_ID=K.ID

WHERE KG.KONT_ID IS NULL

 

В такой проверке значение некоторого выражения сравнивается с каждым из множества значений, возвращенных вложенным запросом.

Синтаксис:

<выражение> <операция сравнения> ANY|ALL (<вложенный запрос>)

Значение выражения поочередно сравнивается с каждым значением, содержащимся в результатах вложенного запроса, в соответствии с заданной операцией сравнения.

Проверка ANY возвращает TRUE (Истина), если любое (хотя бы одно) из этих сравнений дает результат TRUE.

Проверка ALL возвращает TRUE (Истина), если все сравнения дают результат TRUE.

 

Пример 50. Вывести список групп, количество контактов в которых не самое большое.

SELECT G.NAZV, COUNT(*)

FROM GRUPPY G, KONT_GR KG

WHERE G.ID=KG.GR_ID

GROUP BY G.ID, G.NAZV

HAVING COUNT(*) < ANY (SELECT COUNT(*) FROM KONT_GR GROUP BY GR_ID)

 

Пример 51. Вывести список групп, количество контактов в которых самое большое.

SELECT G.NAZV, COUNT(*)

FROM GRUPPY G, KONT_GR KG

WHERE G.ID=KG.GR_ID

GROUP BY G.ID, G.NAZV

HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM KONT_GR GROUP BY GR_ID)

 

Вариант без многократного сравнения:

SELECT G.NAZV, COUNT(*)

FROM GRUPPY G, KONT_GR KG

WHERE G.ID=KG.GR_ID

GROUP BY G.ID, G.NAZV

HAVING COUNT(*) = (SELECT MAX(KOLVO)

FROM (SELECT COUNT(*) AS KOLVO

FROM KONT_GR

GROUP BY GR_ID))

 

Пример 52. Вывести тип вызова, зафиксированный с наибольшим количеством контактов.

Не работает в Microsoft Access:

SELECT T.NAZV, COUNT(DISTINCT N.KONT_ID)

FROM TIPY_VYZ T, VYZOVY V, NOMERA N

WHERE (T.ID=V.TIP_ID) AND (V.NOMER_ID=N.ID)

GROUP BY T.ID, T.NAZV

HAVING COUNT(DISTINCT N.KONT_ID)>=ALL

(SELECT COUNT(DISTINCT N1.KONT_ID)

FROM VYZOVY V1, NOMERA N1

WHERE V1.NOMER_ID=N1.ID

GROUP BY V1.TIP_ID)

 

Работает в Microsoft Access:

SELECT Q.NAZV, COUNT(*)

FROM ( SELECT DISTINCT T.NAZV, N.KONT_ID

FROM TIPY_VYZ T, VYZOVY V, NOMERA N

WHERE (T.ID=V.TIP_ID) AND (V.NOMER_ID=N.ID)) AS Q

GROUP BY Q.NAZV

HAVING COUNT(*) >= ALL

(SELECT COUNT(*)

FROM (SELECT DISTINCT V1.TIP_ID, N1.KONT_ID

FROM VYZOVY V1, NOMERA N1

WHERE V1.NOMER_ID=N1.ID) AS Q1

GROUP BY Q1.TIP_ID)