SQL дозволяє вкладати запити один в другий. Вкладені запити називають підзапитами. Коли вираз виборки вкладений в серединну другої команди SELECT, то внутрішній запит виконується першим. Як правило більшість запитів з підзапитами можуть бути переписані як багатотабличні запити.
Якщо підзапит повертає одне значення, то його можна використовувати скрізь де потрібно порівняти одне значення з другим.
Якщо підзапит повертає багато значень, то його можна використовувати тільки в розділі WHERE.
Наприклад:
SELECT name1, name2,
acc_sum = ( SELECT SUM(summa) FROM account
WHERE key_customer = 2 )
FROM customer
WHERE key_customer = 2
Результат виборки:
name1 name2 acc_sum
Соколов Іван 10500.0
Запит виводить прізвище та ім`я покупця разом з сумою його рахунків. Цей запит можна виконати і з допомогою двотабличного запиту, але тоді він буде виконуватися більш повільно. (account - рахунок, звіт; customer - покупець)
В деяких випадках використовують DISTINCT для гарантії того, що в результаті виконання підзапиту ми отримаємо одне значення.
Наприклад, потрібно знайти всі замовлення, з якими працює продавець, який обслуговує покупця з номером 2001:
SELECT *
FROM zakaz
WHERE nom_prod =
( SELECT DISTINCT nom_prod
FROM zakaz
WHERE nom_pokup=2001 )
У розділі WHERE підзапити використовується як аргумент предикатів: IN, EXIST, SOME, ANY, ALL.
Наприклад, знайти всіх покупців, які зробили замовлення 3 жовтня 1990 року:
SELECT *
FROM customer out
WHERE 03/10/1990 IN
( SELECT zdate
FROM zakaz inn
WHERE out.nom_pokup=inn.nom_pokup )
Предикат EXISTS
Бувають випадки, коли в умові пошуку треба вказати, що з таблиці потрібно вибрати тільки ті записи, для яких підзапит повертає хоч би одне значення. В такому випадку використовують предикат EXISTS. Предикат EXISTS оцінює виборку на фактор існування, тобто перевіряє чи є вказані записи чи ні.
Предикат має наступний синтаксис:
EXISTS <підзапит>
Значенням цього предиката завжди є true або false, і це значення рівно true тоді і тільки тоді, коли результат обчислення підзапиту не пустий. Перед оператором EXISTS не повинно стояти ім`я стовпчика або константи. Список виборки підзапиту, який оброблюється EXISTS зазвичай складається із * (всі поля). Фраза WHERE в такому запиті перевіряє чи існують вибрані записи.
Наприклад, потрібно знайти тих продавців, які отримали товар зі складу:
SELECT DISTINCT nom_prod, FIO
FROM customer out
WHERE EXISTS
( SELECT *
FROM customer inn
WHERE inn.nom_prod=out.nom_prod AND
inn.nom_tov<>out.nom_tov )
Підзапит буде виконуватись стільки разів, скільки записів у зовнішній таблиці.
Так як EXISTS генерує значення false або true (але не unknown), його можна використовувати разом з іншими булевими виразами з допомогою операторів AND, OR, NOT. Найчастіше з EXISTS використовується оператор NOT.
Наприклад, знайти продавців, які мають тільки одного покупця:
SELECT DISTINCT nom_prod
FROM customer out
WHERE NOT EXIST
( SELECT *
FROM customer inn
WHERE inn.nom_prod=out.nom_prod AND
inn.nom_pokup<>out.nom_pokup )
Показати назви всіх компаній з customer де код замовника має відповідний код в таблиці orders (замовлення): компанії, які зробили хоч би одне замовлення
OPEN DATABASE (HOME( ) + 'samples\data\testdata')
SELECT name_company
FROM customer a
WHERE
EXISTS (SELECT *
FROM orders b
WHERE a.code _p= b.code_p)
Предикат SOME або ANY
(деякий, який-небуть, любий)
SOME та ANY виконуються абсолютно однаково і є взаємозамінними. В цих предикатах, так само як і в EXIST, в якості аргументів використовують підзапити.
Синтаксис операторів такий:
<вираз для порівняння> <оператор порівняння> ANY | SOME <підзапит>
Наприклад вираз:
WHERE stowbch > SOME ( SELECT pole FROM tabl)
вказує на те, що значення стовпчика stowbch повинно бути більше хоч би одного (любого) значення в стовпчику pole з таблиці tabl.
Предикати SOME (ANY) дають результат true, false або unknown.
Позначимо через x результат обчислення арифметичного виразу лівої частини предиката, а через S результат обчислення підзапиту.
- Предикат "x <оператор порівняння> SOME S" має значення false, якщо множина S порожня або, якщо значення предиката "x <оператор порівняння> s" рівно false для кожного s, яке входить в S.
- Предикат "x <оператор порівняння> SOME S" має значення true, якщо значення предиката "x <оператор порівняння> s" рівно true хоча б для одного s, яке входить в S.
- В інших випадках значення предиката "x <оператор порівняння> SOME S" рівно unknown.
Наприклад:
Видати всі записи про відправку товарів зі складу, для яких кількість товару більша за середнє значення відправки хоч би одного товару.
SELECT *
FROM rozhod r1
WHERE r1.kilk > SOME
( SELECT AVG(r2.kilk)
FROM rozhod r2
GROUP BY nom_pokup )
Знайти продавців і покупців, які знаходяться в одному місті:
SELECT *
FROM spisok
WHERE city = ANY
( SELECT city
FROM customer )
Spisok
Customer
Query
Id
Fam
city
...
Id
city
...
Id
Fam
city
...
aaa
X
X
aaa
X
bbb
Y
Z
ccc
X
ccc
X
X
ddd
Z
ddd
Z
X
eee
Y
Z
Вибрати всі замовлення, величина яких більша за величину хоч би одного замовлення, зробленого 7 жовтня 1990 року: