14.4. Вкладені запити
За допомогою SQL можна вкладати запити усередину один одного. Щоб виконати основний запит, SQL спочатку повинний оцінити внутрішній запит (його називають підзапитом) усередині речення WHERE чи HAVІNG. Відбувається це традиційним чином, тобто виповнюється вкладений запит, що витягає необхідні для визначення значення предиката дані, а тільки потім - основний. Підзапит повинний вибрати тільки одне поле, а тип даних цього поля повинний збігатися з тим значенням, з яким він буде порівнюватися в предикаті.
Можлива ситуація, коли результатом підзапита є кілька різних значень, це унеможливлює оцінку предиката основного запиту і СКБД видасть помилку. Тому обов'язково потрібно переконатися, що підзапит буде відображати тільки один рядок виводу. Крім того, при використанні підзапиту, що узагалі не виводить ніяких значень, основний запит не виведе ніяких значень: його предикат буде мати невідоме значення.
У деяких випадках варто використовувати DІSTІNCT для того, щоб у під запиті одержати одиночне значення.
Наприклад, запит - вивести ПІБ тих, хто здав всі іспити - повинний бути вкладеним. Для його виконання спочатку треба скласти і виконати запит - скільки іспитів повинний здавати кожен студент (табл. ТаблГруппа і ТаблДисціплина). Потім скласти і виконати запит - скільки іспитів здав кожен студент (табл. ТаблСтудент). І, нарешті, порівняти результати двох запитів - якщо значення збігаються, то ПІБ вивести в результат підсумкового запиту.
Для приклада спочатку виконаємо всі запити окремо, а потім покажемо, що результат буде еквівалентний одному вкладеному запиту.
Запит: Визначити кількість іспитів, що повинний здавати кожен студент. |
|||||||||||||||||||||
SELECT ТаблГрупа.ПІБ, Count(ТаблГрупа.Група) AS [Кількість іспитів] FROM ТаблГрупа, ТаблДисципліна WHERE ((ТаблГруппа.Група)= [ТаблДисципліна].[Група] AND (ТаблДисципліна.ВидКонтролю)='Іспит') GROUP BY ТаблГрупа.ПІБ, ТаблДисципліна.Група, ТаблДисципліна.ВидКонтролю; |
ПІБ
Кількість
іспитів
Владіміров
В. А.
3
Іванова
Е. А.
1
Крилова
Т. С.
3
Міронов
А. В.
3
Петров
Ф. І.
3
Сідоров
К. А.
3
Стєпанова
К. Е.
3
Трофімов
П. А.
1
Уткіна
Н. В.
1 |
||||||||||||||||||||
Запит: Визначити кількість іспитів, що здав кожен студент. |
|||||||||||||||||||||
SELECT ПІБ, Count(ТаблСтудент.ПІБ) AS [ Здано іспитів ] FROM ТаблСтудент WHERE Оцінка>2 GROUP BY [ПІБ]; |
Результат:
ПІБ
Здано іспитів
Владіміров
В. А.
3
Іванова
Е. А.
1
Крилова
Т. С.
3
Міронов
А. В.
1
Петров
Ф. І.
3
Сідоров
К. А.
2
Стєпанова
К. Е.
1
Трофімов
П. А.
2
Уткіна
Н. В.
1 |
||||||||||||||||||||
Тепер порівнюючи результати виконання двох запитів можна зробити висновок про те, що сесію здали Іванова Е. А. і Трофімов П. А. Аналогічний результат виходить відразу при виконанні вкладеного запиту.
Запит: вивести ПІБ тих, хто здав всі іспити. |
||||||||
SELECT ТаблСтудент.ПІБ FROM ТаблСтудент WHERE (ТаблСтудент.Оцінка>2) GROUP BY ТаблСтудент.ПІБ HAVING (Count(ТаблСтудент.ПІБ)=(SELECT COUNT(ТаблГрупа.ПІБ) FROM ТаблГрупа, ТаблДисципліна WHERE ТаблГрупа.Група=ТаблДисципліна.Група AND ТаблДисципліна.ВидКонтролю='Іспит' AND ТаблГрупа.ПІБ = ТаблСтудент.ПІБ)); Або еквівалентний більш короткий запис SELECT ПІБ FROM ТаблСтудент WHERE Оцінка>2 GROUP BY [ПІБ] HAVING COUNT(*) = (SELECT COUNT(*) FROM ТаблГрупа, ТаблДисципліна WHERE ТаблГрупа.Група=ТаблДисципліна.Група AND ТаблДисципліна.ВидКонтролю='Іспит' AND ТаблГрупа.ПІБ = ТаблСтудент.ПІБ)); |
Результат:
ПІБ
Владіміров
В.А.
Іванова
Е. А.
Крилова
Т.С.
Петров
Ф.І.
Трофімов
П. А.
Уткіна
Н.В. |
|||||||
