
- •Информационное обеспечение систем управления Построение запросов при работе с базой данных (Учебное пособие)
- •Тестовая база данных
- •Выборка данных. Команда select
- •Синтаксис оператора select
- •Простые варианты поиска данных
- •Упорядочение результата запроса. Предложение order by
- •Использование ключевого слова distinct
- •Предложение where
- •Синтаксис предложения where
- •Использование операторов сравнения
- •Использование варианта between
- •Проверка на присутствие в списке значений (вариант in)
- •Проверка на пустое значение
- •Поиск в строковых столбцах
- •Вариант like
- •Использование логических операций в условиях поиска
- •Порядок выполнения логических операций
- •Преобразование данных при выборке
- •Обобщение Данных с помощью Агрегатных Функций
- •Использование distinct с count
- •Предложение group by
- •Предложение having
- •Соединение таблиц
- •Внутренние соединения (связывание по равенству)
- •Внешние соединения
- •Левое внешнее соединение
- •Правое внешнее соединение
- •Полное внешнее соединение
- •Более сложные примеры соединений
- •Рефлексивное соединение, или самосоединение
- •Использование подзапросов в операторах sql
- •Выбор одного
- •Использование в подзапросе агрегатных функций
- •Связанные подзапросы
- •Использование оператора exists
- •Использование варианта in с подзапросами
- •Использование not exists
- •Объединение запросов
- •Команда union
- •Добавление данных. Команда insert
- •Добавление отдельной строки
- •Добавление группы строк
- •Обновление уже имеющихся данных. Команда update
- •Удаление данных из таблиц. Команда delete
- •Генераторы и их использование
- •Создание генераторов
- •Использование генераторов
- •Увеличение значения генератора
- •Получение значения генератора в приложение
- •Триггер
Использование оператора exists
EXISTS переводится как «существует» - это оператор, который возвращает логическое выражение (истина или ложь). Он берет подзапрос как аргумент и получает «истина», если тот производит любой вывод или «ложь», если тот не делает этого. Иными словами функция EXISTS возвращает значение «истина», если подзапрос возвращает хотя бы одну строку и «ложь», если подзапрос не возвращает ни одной строки. Функция EXISTS используется в условии WHERE.
Так как внутренний оператор SELECT содержит произвольное количество столбцов, вместо списка столбцов обычно используют символ * (звездочка), что означает, что выбираются все столбцы.
В качестве примера выведем фамилию, имя, отчество членов экипажа летавших в феврале 2008 года (если в таблице EQUIPAGE существует строка для выбранной личности с атрибутом EQ_FL_DATE попадающим в февраль 2008 года).xlviii
SELECT PR_NAME2 AS "Имя",
PR_NAME3 AS "Отчество",
PR_NAME AS "Фамилия"
FROM PERSON
WHERE EXISTS( SELECT * FROM EQUIPAGE E
WHERE E.EQ_FL_DATE BETWEEN '1.02.08' AND '29.02.08'
AND E.EQ_PR_CODE = PERSON.PR_CODE )
Для каждой строки-кандидата внешнего запроса (представляющей личность, проверяемую в настоящее время), внутренний запрос находит строки, которые относятся к этой личности (совпадение E.EQ_PR_CODE = PERSON.PR_CODE) и проверяет попадание даты вылета (EQ_FL_DATE) в заданный интервал.
Альтернативным способом получения такого же результата будет использование связывания таблиц PERSON и EQUIPAGE и исключения дубликатов при помощи ключевого слова DISTINCT.
Использование варианта in с подзапросами
Еще одним способом решить поставленную задачу является использование варианта IN. То есть во внутреннем запросе нужно из таблицы EQUIPAGE найти коды личностей (EQ_PR_CODE), даты вылета которых (EQ_FL_DATE) попадают в заданный интервал. Во внешнем запросе выводим фамилию, имя, отчество из таблицы PERSON коды которых, попадают в найденный перечень.xlix
SELECT PR_NAME2 AS "Имя",
PR_NAME3 AS "Отчество",
PR_NAME AS "Фамилия"
FROM PERSON
WHERE PR_CODE IN (SELECT EQ_PR_CODE FROM EQUIPAGE
WHERE EQ_FL_DATE BETWEEN '1.02.08' AND '29.02.08' )
Использование not exists
Наиболее часто вместе с EXISTS используется оператор отрицания NOT. Если в условии нужно, чтобы строк запроса не существовало, использование подзапроса зачастую является единственной возможностью.
Получим список членов экипажа, которые совершали полет в январе 2008 года, и при этом не разу не летали в феврале. Приведем первый вариант с использованием NOT EXISTS:l
SELECT DISTINCT P.PR_NAME2 AS "Имя",
P.PR_NAME3 AS "Отчество",
P.PR_NAME AS "Фамилия"
FROM PERSON P
INNER JOIN EQUIPAGE E1 ON E1.EQ_PR_CODE = P.PR_CODE
WHERE (E1.EQ_FL_DATE BETWEEN '1.01.08' AND '31.01.08')
AND NOT EXISTS
( SELECT * FROM EQUIPAGE E2
WHERE E2.EQ_FL_DATE BETWEEN '1.02.08' AND '29.02.08'
AND E2.EQ_PR_CODE = P.PR_CODE )
Разберем полученный запрос – внешний запрос выводит фамилию, имя, отчество для всех членов экипажа которые совершали полет в январе 2008 года, ключевое слово DISTINCT нужно, чтобы даже те члены экипажа, которые летали неоднократно, выводились только один раз. Во внешнем запросе используются псевдонимы таблиц P для PERSON и E1 для EQUIPAGE. В предложении WHERE соединяем два условия, первое ограничивает выводимый список членов экипажа теми, которые совершали полет в январе. Второе условие требует, чтобы текущая личность не совершала полет в течении февраля, т.е. чтобы за указанный период для этой личности не существовало строки в таблице EQUIPAGE. Во внешнем запросе для таблицы EQUIPAGE используется псевдоним Е2.
Приведем вариант этого запроса с использованием NOT IN.li
SELECT DISTINCT P.PR_NAME2 AS "Имя",
P.PR_NAME3 AS "Отчество",
P.PR_NAME AS "Фамилия"
FROM PERSON P
INNER JOIN EQUIPAGE E1 ON E1.EQ_PR_CODE = P.PR_CODE
WHERE (E1.EQ_FL_DATE BETWEEN '1.01.08' AND '31.01.08')
AND (NOT P.PR_CODE IN
( SELECT EQ_PR_CODE FROM EQUIPAGE
WHERE EQ_FL_DATE BETWEEN '1.02.08' AND '29.02.08' ))
Здесь мы делаем следующее – во внутреннем подзапросе находим коды всех личностей из таблицы EQUIPAGE, которые совершали полет в феврале, внешний запрос выводит фамилию, имя, отчество для тех кто летал в январе 2008 и при этом среди них нет тех, кто содержится в результате вывода подзапроса (т.е. те кто летал в феврале).