Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Авт_ПМП / Tema_SQL.doc
Скачиваний:
10
Добавлен:
05.02.2016
Размер:
462.34 Кб
Скачать

Підзапити

Звернімося до таблиць Vidomist(kod,year,month,D), tpp(d_l,d_r, p,c) i Osoba(kod, priz). Нагадаємо, що в таблиці Vidomist (kod,year,month,D – її поля) зберігається інформація про нараховану зарплату співробітників за певний рік і місяць. Таблиця tpp містить дані для обрахування податку на прибуток, а таблиця Osoba інформацію про персональний склад. Нехай нам потрібно сформувати список осіб з такими колонками: “ Прізвище ”,” Нараховано ”, які одержують нараховану зарплату вищу за середню середню нараховану зарплату за 2-й місяць 2002 року. Середню нараховану зарплату за 2-й місяць 2002 року визначить такий запит:

SELECT AVG(D)

FROM Vidomist

WHERE year=2002 AND mounth=2

Середня нарахована зарплата становить 500 грн.

Для вирішення цієї задачі потрібно а) знайти чому дорівнює середня зарплата а потім б) ті рядки, в яких нарахована сума перевищує середню зарплату, включити до результуючої таблиці. Запит, який вирішує поставлену задачу, наведено нижче:

SELECT a.priz AS Прізвище, b.D AS Нараховано

FROM (Osoba AS a INNER JOIN Vidomist AS b ON a.kod=b.kod)

WHERE b.year=2002 AND b.mounth=2 AND b.D> (SELECT AVG(D) FROM Vidomist WHERE year=2002 AND mounth=2)

Результуюча таблиця матиме вид:

Прізвище

Нараховано

Сидоров

600

Пояснимо цей SELECT-оператор. Запит

SELECT AVG(D)

FROM Vidomist

WHERE year=2002 AND mounth=2

який розташований у фразі WHERE першого SELECT’у (він взятий у дужки) називають підзапитом. На відміну від основного запиту, якого ще називають зовнішнім запитом, підзапит ще називають внутрішнім запитом. Цей підзапит знаходить середню нараховану зарплату. Потім запит відбирає ті рядки, в яких нарахована зарплата перевищує число (в цьому конкретному випадку воно дорівнює 500), знайдене підзапитом.

Якщо ж потрібно скласти список співробітників, які мають нараховану зарплату вище середньої, вказавши при цьому на скільки вона перевищує середню, то запит матиме вид:

SELECT a.priz AS Прізвище, b.D AS Нараховано, b.D-(SELECT AVG(D) FROM Vidomist WHERE year=2002 AND mounth=2) AS Перевищення

FROM (Osoba AS a INNER JOIN Vidomist AS b ON a.kod=b.kod)

WHERE b.year=2002 AND b.mounth=2 AND b.D> (SELECT AVG(D) FROM Vidomist WHERE year=2002 AND mounth=2)

Результуюча таблиця матиме вид:

Прізвище

Нараховано

Перевищення

Сидоров

600

100

Якщо ж середню величину зарплати обраховувати виходячи з суми, яку повинні видавати на руки (нарахована мінус податок на прибуток) і запит має повертати такі колонки: “ Прізвище ”,” Нараховано ”,” Сума податку ” і “ До виплати ”, то запит матиме вид:

SELECT a.priz AS Прізвище, b.D AS Нараховано, (b.D-c.d_l)*c.p+c.c AS [Сума податку], b.D-((b.D-c.d_l)*c.p+c.c) AS [До виплати]

FROM (Osoba AS a INNER JOIN Vidomist AS b ON a.kod=b.kod) INNER JOIN tpp AS c ON (b.D>c.d_l) AND (b.D<=c.d_r)

WHERE b.year=2002 AND b.mounth=2 AND (b.D-((b.D-c.d_l)*c.p+c.c))> (SELECT AVG(b.D-((b.D-c.d_l)*c.p+c.c)) FROM Osoba a, Vidomist b, tpp c WHERE a.kod=b.kod AND (b.D>c.d_l) AND (b.D<=c.d_r) AND b.year=2002 AND b.mounth=2)

Результуюча таблиця матиме вид:

Прізвище

Нараховано

Сума податку

До виплати

Сидоров

600

105,55

494,45

Підзапит цього запиту має вид:

SELECT AVG(b.D-((b.D-c.d_l)*c.p+c.c))

FROM Osoba a, Vidomist b, tpp c

WHERE a.kod=b.kod AND (b.D>c.d_l) AND (b.D<=c.d_r) AND b.year=2002 AND b.mounth=2

Підзапит може вказуватись безпосередньо після операторів зрівнювання (=, <, >, <=, >=, <>) у фразах WHERE i HAVING. Текст підзапиту потрібно брати в дужки. До підзапитів застосовують такі правила і обмеження.

  1. В підзапитах не повинна використовуватись фраза ORDER BY, хоч вона може використовуватись у зовнішньому запиті.

  2. За змовчуванням імена стовпчиків в підзапиті відносяться до таблиць, які вказані у фразі FROM підзапиту. Разом з тим допускається посилатись і на стовпчики таблиць, які вказані у фразі FROM зовнішнього запиту, для чого використовуються аліаси.

  3. Якщо підзапит є одним з двох операндів оператора зрівнювання, то підзапит повинен вказуватись в правій частині оператора зрівнювання.

  4. Якщо підзапит є одним з двох операндів оператора зрівнювання, то підзапит має повертати єдине значення.

Існує три типи підзапитів.

  • Скалярний підзапит – це підзапит, який повертає єдине значення. У вищенаведених прикладах використовувався скалярний підзапит.

  • Строковий підзапит – це підзапит, який повертає значення декількох стовпчиків у вигляді одного рядка.

  • Табличний підзапит - це підзапит, який повертає значення одного або більше стовпчиків таблиці, які розташовані в більш ніж одному рядку. Табличний підзапит може використовуватись кругом де допускається вказувати таблицю – наприклад, як операнд предикату IN.

Ключові слова ANY i ALL

Ключові слова ANY i ALL використовуються лише з підзапитами, які повертають один стовпчик чисел. Якщо перед підзапитом стоятиме ключове слово ALL, умова зрівняння вважається істинною, якщо вона виконується для всіх значень в результуючому стовпчику підзапиту. Наприклад, запит

SELECT *

FROM Vidomist

WHERE D> ALL (SELECT D FROM Vidomist WHERE kod IN (1,2))

Результат наведено нижче

kod

Year

mounth

D

3

2002

1

2709.98

В данному конкретному випадку внутрішній запит

SELECT D FROM Vidomist WHERE kod IN (1,2)

відбере такі значення: {367.78,1309.55,400,500}.

Очевидно, умова D> ALL (SELECT D FROM Vidomist WHERE kod IN (1,2))

еквівалентна умові D> (SELECT MAX(D) FROM Vidomist WHERE kod IN (1,2)).

Власне кажучи, цей запит еквівалентний запиту (дасть той же результат)

SELECT *

FROM Vidomist

WHERE D> (SELECT MAX(D) FROM Vidomist WHERE kod IN (1,2))

Якщо перед підзапитом стоятиме ключове слово ANY, умова зрівняння вважається істинною, якщо вона виконується хоча б для одного значення в результуючому стовпчику підзапиту. Наприклад, умова

D> ANY(SELECT D FROM Vidomist WHERE kod IN (1,2))

істинна тоді і тільки тоді коли вона істинна хоча б для одного значення, яке відбере внутрішній запит. Отже, любе D, яке більше 400, задовольнить нашій умові.

Результатом запиту

SELECT *

FROM Vidomist

WHERE D> ANY (SELECT D FROM Vidomist WHERE kod IN (1,2))

буде таблиця:

kod

Year

mounth

D

1

2002

1

367.78

2

2002

1

1309.55

3

2002

1

2709.98

2

2002

2

500

3

2002

2

600

Очевидно, цей запит буде еквівалентний запиту

SELECT *

FROM Vidomist

WHERE D> (SELECT MIN(D) FROM Vidomist WHERE kod IN (1,2))

Соседние файлы в папке Авт_ПМП