- •ОГЛАВЛЕНИЕ
- •3. Простые варианты поиска данных
- •3.2. Использование ключевого слова DISTINCT
- •3.3. Предложение WHERE
- •4.1. Использование DISTINCT с COUNT
- •4.3. Предложение HAVING
- •5.2. Внешние соединения
- •6. ИСПОЛЬЗОВАНИЕ ПОДЗАПРОСОВ В ОПЕРАТОРАХ SQL
- •6.4. Использование оператора EXISTS
- •6.5. Использование варианта IN с подзапросами
- •6.6. Использование NOT EXISTS
- •8. ДОБАВЛЕНИЕ ДАННЫХ. КОМАНДА INSERT
- •8.1. Добавление отдельной строки
- •9. ОБНОВЛЕНИЕ УЖЕ ИМЕЮЩИХСЯ ДАННЫХ.
- •КОМАНДА UPDATE
- •10. УДАЛЕНИЕ ДАННЫХ ИЗ ТАБЛИЦ. КОМАНДА DELETE
- •11. ГЕНЕРАТОРЫ И ИХ ИСПОЛЬЗОВАНИЕ
- •11.1. Создание генераторов
- •ПРИМЕРЫ ЗАПРОСОВ
INNER JOIN TICKET TON T.TC_PR_CODE = P .P R C O D E
WHERE T.TC_FL_DATE BETWEEN '1.01.08' AND '31 12 08' AND T.TC PR CODE IN
(SELECT TC_PR_ CODE FROM TICKET
WHERE TC_FL_DATE BETWEEN '1.01 08' AND '31.12.08'
GROUP BY TC_PR_CODE HAVING COUNTC) > 1)
ORDER BY P.PR_NAME, P.PRJNAME2
В результате выполнения запроса получим:
Листинг 24
Список пассажиров, которые приобрели более одного билета в течение 2008 г., также выводится номер авиалинии и дата вылета из билета (с использованием GROUP BY и HAVING в подзапросе)
Имя |
Отчество |
Фамилия |
Номер авиа |
Дата вылета |
|
линии |
|||||
|
|
|
|
||
Константин |
Игоревич |
Баталов |
124 |
08.01.2008 |
|
Константин |
Игоревич |
Баталов |
125 |
11.01.2008 |
|
Мария |
Ивановна |
Выгузова |
124 |
08.01.2008 |
|
Мария |
Ивановна |
Выгузова |
125 |
11.01.2008 |
|
Василий |
Александрович |
Глазов |
124 |
08.01.2008 |
|
Василий |
Александрович |
Глазов |
125 |
11.01.2008 |
1
6.4. Использование оператора EXISTS
EXISTS переводится как «существует» - это оператор, который возвращает логическое выражение («истина» или «ложь»). Он берет подзапрос как аргумент и получает «истина», если тог производит любой вывод, или «ложь», если тот не делает этого. Иными слова ми, функция EXISTS возвращает значение «истина», если подза прос возвращает хотя бы одну строку, и «ложь», если подзапрос не возвращает ни одной строки. Функция EXISTS используется в условии WHERE.
Поскольку внутренний оператор SELECT содержит произволь ное количество столбцов, вместо списка столбцов обычно исполь зуют символ * (звездочка), что означает, что выбираются все столб цы.
В качестве примера выведем фамилию, имя, отчество членов экипажа, летавших в феврале 2008 г. (если в таблице EQUIPAGE
существует |
строка для выбранной личности с атрибутом |
EQ_FL_DATE попадающим в февраль 2008 года).48 |
|
SELECT |
PRJNAME2 AS "Имя", |
PRJNAME3 AS "Отчество",
PR_NAME AS "Фамилия"
FROM PERSON
WHERE EXISTS (SELECT * FROM EQUIPAGE E
WHERE E.EQJFLJDAТЕ BETWEEN '1.02.08' AND '29.02.08'
AND E.EQ_PR_CODE = PERSON.PR CODE)
Для каждой строки-кандидата внешнего запроса (представ ляющей личность, проверяемую в настоящее время) внутренний запрос находит строки, которые относятся к этой личности (совпа дение E.EQ PRjCODE = PERSON.PR_CODE), и проверяет попада ние даты вылета (EQ_FL_DA ТЕ) в заданный интервал.
Альтернативным способом получения такого же результата бу дет использование связывания таблиц PERSON и EQUIPAGE и ис ключения дубликатов при помощи ключевого слова DISTINCT.
6.5. Использование варианта IN с подзапросами
Еще одним способом решить поставленную задачу является использование варианта IN, т.е. во внутреннем запросе нужно из таблицы EQUIPAGE найти коды личностей (EQ_PR_CODE), да ты вылета которых (EQ_FL_DATE) попадают в заданный интервал. Во внешнем запросе выводим фамилию, имя, отчество из таблицы PERSON, коды которых попадают в найденный перечень49
SELECT PRJNAME2 AS "Имя",
PR_NAME3 AS "Отчество",
PR_NAME AS "Фамилия"
FROM PERSON
WHERE PR CODE IN (SELECTEQ_PR_CODE FROM EQUIPAGE WHERE EQJFLJDATE BETWEEN 4.02.08' AND '29.02.08')
6.6. Использование NOT EXISTS
Наиболее часто вместе с EXISTS используется оператор отри цания NOT. Если в условии нужно, чтобы строк запроса не сущест вовало, использование подзапроса зачастую является единственной возможностью.
Получим список членов экипажа, которые |
совершали полег |
в январе 2008 года, и при этом ни разу не летали |
в феврале. Приве |
дем первый вариант с использованием NOT EXISTS50:
SELECT DISTINCT |
P.PR_NAME2 AS "Имя", |
|
|
P.PRJNAME3 |
AS "Отчество", |
|
P.PRJNAME |
AS "Фамилия" |
FROM PERSON P
INNER JOIN EQUIPAGE E1 ON E1.EQ_PR_CODE = P.PRjCODE WHERE (E1.EQJFLJDAТЕ BETWEEN '1.01.08' AND
'31.01.08')
AND NOT EXISTS
( SELECT * FROM EQUIPAGE E2
WHERE E2.EQ_FLJDATE BETWEEN '1.02.08'AND '29.02.08' AND E2.EQ_PR_CODE = P.PR_CODE)
Разберем полученный запрос: внешний запрос выводит фами лию, имя, отчество для всех членов экипажа, которые совершали полет в январе 2008 г., ключевое слово DISTINCT нужно, чтобы даже те члены экипажа, которые летали неоднократно, выводились только один раз. Во внешнем запросе используются псевдонимы таблиц Р для PERSON и Е1 для EQUIPAGE. В предложении WHERE соединяем два условия, первое ограничивает выводимый список членов экипажа теми, которые совершали полег в январе. Второе условие требует, чтобы эта личность не совершала полет в течение февраля, т.е. чтобы за указанный период для этой лично сти не существовало строки в таблице EQUIPAGE. Во внешнем за просе для таблицы EQUIPAGE используется псевдоним Е2.
Приведем вариант этого запроса с использованием NOT IN51
SELECT DISTINCT P.PR_NAME2 AS "Имя",
P.PR NAME3 AS "Отчество",
P.PRJNAME AS "Фамилия"
FROM PERSON P
INNER JOIN EQUIPAGE E1 ON E1.EQ_PR_CODE = P.PR_CODE
INNER JOIN CITY CFROM ON CFROM.CT_CODE = AFROM.AP_CT_CODE
INNER JOIN AIRPORT A TO ON ATO.AP_CODE =
AL.AL_AP_TO
INNER JOIN CITY CTO ON CTO.CT_CODE =
ATO.AP_CT_CODE
WHERE CFROM.CT_NAME - 'Пермь' AND CTO.CT_NAME -
71Доскзд'
AND EQ.EQ_FL_DA ТЕ - '11.01.2008'
UNION
SELECT P.PR_NAME2, P.PR_NAME3, P.PRJNAME,
CAST('nacca>Kup‘ AS CHAR(12)),
CAST(TC.TC_SEAT AS VARCHAR(20)) FROM PERSON P
INNER JOIN TICKET TC ON TC.TC_PR_CODE = P.PR_CODE INNER JOIN TARIFF TR ON TR.TR_CODE =
TC.TC_TR_CODE
INNER JOIN AIRPORT AFROM ON AFROM.AP_CODE = TR. TR_AP_FROM
INNER JOIN CITY CFROM ON CFROM.CT_CODE = AFROM.AP_CT_CODE
INNER JOIN AIRPORT ATO ON ATO.AP_CODE =
TR.TR_AP_TO
INNER JOIN CITY CTO ON CTO.CT_CODE =
ATO.AP_CT_CODE
WHERE CFROM.CTJNAME = 'Пермь' AND CTO.CTJNAME = 'Москва'
AND TC .TC _FL_D A TE -'11.01.2008'
В результате выполнения запроса получаем список:
Листинг 25
Результат объединения запросов (команды UNION) - список всех прилетевших из Перми в Москву 11.01.2008
Имя |
Отчество |
Фамилия |
Тип |
Роль/Место |
Александр |
Александрович |
Чудинов |
Пассажир |
5Г |
Владимир |
Николаевич |
Карпов |
Пассажир |
ЗБ |
Владимир |
Юрьевич |
Войтович |
Пассажир |
2Б |