Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информационное обеспечение систем управления. Построение запросов пр.pdf
Скачиваний:
4
Добавлен:
15.11.2022
Размер:
3.76 Mб
Скачать

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

Имя

Отчество

Фамилия

Тип

Роль/Место

Александр

Александрович

Чудинов

Пассажир

Владимир

Николаевич

Карпов

Пассажир

ЗБ

Владимир

Юрьевич

Войтович

Пассажир