Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2584

.pdf
Скачиваний:
1
Добавлен:
15.11.2022
Размер:
1.88 Mб
Скачать

SELECT, в окончательном результате она появляется только один раз.

Любое число предложений SELECT может быть соединено операторами UNION. Можно расширить данный пример с тем, чтобы включить номера красных деталей, дополнив приведенный выше запрос следующей конструкцией:

UNION

SELECT НОМЕР_ДЕТАЛИ

FROM Р

WHERE ЦВЕТ = ’Красный’

перед заключительной точкой с запятой. Заметим, что такого же результата можно было достигнуть, добавляя к первому из первоначальных предложений SELECT фразу OR ЦВЕТ = ’Красный’.

Любая фраза ORDER BY в запросе должна входить как часть только в последнее предложение SELECT и должна указывать столбцы, по которым осуществляется упорядочение, путем указания их порядковых позиций, т. е. их номеров.

В связи с оператором UNION часто оказывается полезной возможность включения констант во фразу SELECT. Например, можно указать, какому из двух условий WHERE удовлетворяет каждая из отдельных деталей:

SELECT НОМЕР_ДЕТАЛИ, ’ее вес> 16 фунтов’

FROM Р

WHERE ВЕС > 16 UNION

SELECT НОМЕР_ДЕТАЛИ, ’деталь поставляется S2’

FROM SP

WHERE НОМЕР_ПОСТАВЩИКА = ’S2' ORDER BY 2, 1;

Результат:

P1

деталь поставляется S2

P2

деталь поставляется S2

P2

ее вес> 16 фунтов

P3

ее вес> 16 фунтов

P6

ее вес> 16 фунтов

 

300

Когда строковая константа выступает в качестве элемента, подлежащего выборке, считается, что она имеет тип VARCHAR и длину, равную числу литер в константе, и

допускаются неопределенные значения.

Может возникнуть желание узнать, поддерживаются ли в языке SQL какие-либо аналоги операторов

INTERSECTION (пересечение) и DIFFERENCE (разность),

поскольку объединение, пересечение и разность в теоретико-множественных рассмотрениях обычно выступают совместно. Пересечение двух множеств представляет собой множество всех элементов, принадлежащих обоим исходным множествам.

Разность двух множеств — это множество элементов, принадлежащих первому исходному множеству, но не принадлежащих второму. В языке SQL эти два оператора непосредственно не поддерживаются, но каждый из них может быть смоделирован с помощью функции EXISTS. Пусть, например, А и В — таблицы, состоящие из единственного столбца, а именно, столбца номеров поставщиков. Пусть А представляет «поставщиков из Лондона», а В — «поставщиков, которые поставляют деталь Р1».

Тогда

SELECT НОМЕР_ПОСТАВЩИКА

FROM А WHERE EXISTS

(SELECT НОМЕР_ПОСТАВЩИКА

FROM В

WHERE В.НОМЕР_ПОСТАВЩИКА = А.НОМЕР_ПОСТАВЩИКА);

представляет пересечение А и В, т.е. поставщиков из Лондона, которые поставляют деталь Р1, а

SELECT НОМЕР_ПОСТАВЩИКА

FROM А

WHERE NOT EXISTS

(SELECT НОМЕР_ПОСТАВЩИКА

301

FROM В

WHERE В.НОМЕР_ПОСТАВЩИКА = А.НОМЕР_ПОСТАВЩИКА);

представляет разность между А и В (в указанном порядке), т. е. поставщиков из Лондона, которые не поставляют деталь Р1. Упражнение. Что представляет собой разность между В и А (именно в этом порядке)?

Заключение

Теперь мы рассмотрели все возможности предложения SELECT языка SQL. Чтобы завершить эту часть, приведем весьма изощренный пример, который показывает, каким образом многие (но отнюдь не все) эти средства могут быть использованы вместе в едином запросе. Рассмотрим также концептуальный алгоритм обработки SQL — запросов общего вида.

Многоаспектный пример

Выдать номер детали, вес в граммах, цвет и максимальный объем поставки для всех красных и голубых деталей, таких, что общий объем их поставки больше, чем 350, исключая при этом из общего объема все такие поставки, для которых количество меньше или равно 200 деталей. Результат упорядочить по убыванию номеров деталей в рамках возрастающих значений этого максимального объема поставки.

SELECT P.НОМЕР_ДЕТАЛИ, ’вес в граммах = ’, Р.ВЕС*454, Р.ЦВЕТ

’максимальн ый объем поставки

=’,

МАХ (SP.КОЛИЧЕСТВО)

FROM Р, SP

302

WHERE Р.НОМЕР_ДЕТАЛИ = SP.НОМЕР_ДЕТАЛИ AND Р.ЦВЕТ IN (’Красный’, ’Голубой’)

AND SP.КОЛИЧЕСТВО > 200

GROUP BY Р.НОМЕР_ДЕТАЛИ, Р.ВЕС, Р.ЦВЕТ

HAVING SUM (КОЛИЧЕСТВО) > 350 ORDER BY 6, P.НОМЕР_ДЕТАЛИ DESC;

Результат:

 

 

 

 

 

НОМЕР_

 

 

ЦВЕТ

 

 

ДЕТАЛИ

 

 

 

 

 

P1

вес в

5448

Красный

максима

300

 

граммах =

 

 

льный

 

 

 

 

 

объем

 

 

 

 

 

поставки

 

 

 

 

 

=

 

P5

вес в

5448

Голубой

максима

400

 

граммах =

 

 

льный

 

 

 

 

 

объем

 

 

 

 

 

поставки

 

 

 

 

 

=

 

P3

вес в

7718

Голубой

максима

400

 

граммах =

 

 

льный

 

 

 

 

 

объем

 

 

 

 

 

поставки

 

 

 

 

 

=

 

Пояснение. Фразы предложения SELECT применяются в таком порядке, в котором они записаны, за исключением самой фразы SELECT, которая применяется между фразами HAVING и ORDER BY, если они имеются. В данном примере, следовательно, можно представить себе, что результат строится следующим образом.

1.FROM. В результате обработки фразы FROM создается новая таблица, которая является декартовым произведением таблиц Р и SP.

2.WHERE. Из результата шага 1 исключаются все строки, не удовлетворяющие фразе WHERE. В данном примере исключаются строки, не удовлетворяющие предикату:

P.HOMEP_ДЕТАЛИ = SP.HOMEP_ДЕТАЛИ AND Р.ЦВЕТ

303

IN (’Красный’, ’Голубой’) AND SР.КОЛИЧЕСТВО > 200.

3.GROUP BY. Результат шага 2 группируется по значениям поля (полей), указанного во фразе GROUP BY. В нашем примере это поля Р.НОМЕР_ДЕТАЛИ, Р.ВЕС и Р.ЦВЕТ.

4.HAVING. Группы, не удовлетворяющие условию SUM (КОЛИЧЕСТВО) > 350,

исключаются из результата, полученного на шаге 3.

5.SELECT. Каждая группа, полученная на шаге 4, следующим образом генерирует единственную строку для результата. Во-первых, из группы выделяются номер детали, вес, цвет и максимальный объем поставки. Вовторых, вес преобразуется в граммы. В-третьих, в соответствующие места полученной строки вставляются две строковые константы ’вес в граммах=’ и ’максимальный объем поставки=’.

6.ORDER BY. Результат шага 5 упорядочивается в соответствии со спецификацией фразы ORDER BY для получения

окончательного результата.

Конечно, приведенный выше запрос весьма сложен, но представим себе, какую он выполняет работу. Обычная программа, в другом языке, которая выполняет ту же самую работу, вполне могла бы составить девять страниц по сравнению только с девятью строками, приведенными выше. При этом работа, необходимая для того, чтобы эта программа стала действующей, значительно больше, чем это необходимо для формулировки приведенного варианта запроса на языке SQL. Большинство запросов на практике будет, конечно, во всяком случае, значительно проще по сравнению с ним.

Упражнения

Как и в предыдущей части, все следующие упражнения основаны на базе данных поставщиков-деталей-изделий. В каждом из них требуется записать предложение SELECT для указанного запроса, за исключением упражнений 15—18 и 26.

304

Для удобства повторим здесь структуру рассматриваемой базы данных:

S (НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, СОСТОЯНИЕ, ГОРОД)

P (НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС, ГОРОД)

J (НОМЕР_ИЗДЕЛИЯ, НАЗВАНИЕ, ГОРОД)

SPJ (НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ, НОМЕР_ИЗДЕЛИЯ,

КОЛИЧЕСТВО)

В каждом разделе упражнения упорядочены приблизительно в порядке возрастания их сложности. Необходимо попытаться выполнить, по крайней мере, некоторые из легких упражнений в каждой группе. Упражнения 12—18 являются весьма трудными.

Подзапросы

1.Выдать названия изделий, для которых поставляются детали поставщиком S1.

2.Выдать цвета деталей, поставляемых поставщиком

S1.

3.Выдать номера деталей, поставляемых для какоголибо изделия в Лондоне.

4.Выдать номера изделий, использующих, по крайней мере, одну деталь, поставляемую поставщиком S1.

5.Выдать номера поставщиков, поставляющих, по крайней мере, одну деталь, поставляемую, по крайней мере, одним поставщиком, который поставляет, по крайней мере, одну красную деталь.

6.Выдать номера поставщиков, имеющих состояние меньшее, чем у поставщика S1.

7.Выдать номера поставщиков, поставляющих детали для какого-либо изделия с деталью Р1 в количестве, большем,

305

чем средний объем поставок детали Р1 для этого изделия. Примечание. В этом упражнении нужно использовать стандартную функцию AVG.

Квантор EXISTS

8.Повторите упражнение 3.3 и используйте в Вашем решении EXISTS.

9.Повторите упражнение 3.4 и используйте в Вашем решении EXISTS.

10.Выдать номера изделий, для которых не поставляет какой-либо красной детали поставщик из Лондона.

11.Выдать номера изделий, для которых детали полностью поставляет поставщик S1.

12.Выдать номера деталей, поставляемых для всех изделий в Лондон.

13.Выдать номера поставщиков, поставляющих одну и ту же деталь для всех изделий.

14.Выдать номера изделий, для которых поставляются, по крайней мере, все детали, имеющиеся у поставщика S1.

Для следующих четырех упражнений (15—18) преобразуйте приведенное предложение SELECT языка SQL обратно в его эквивалент на естественном языке.

15.SELECT DISTINCT НОМЕР_ИЗДЕЛИЯ

FROM SPJ SPJX WHERE NOT EXISTS

(SELECT * FROM SPJ SPJY

WHERE SPJY.НОМЕР_ИЗДЕЛИЯ = SPJX.НОМЕР_ИЗДЕЛИЯ

AND NOT EXISTS (SELECT * FROM SPJ SPJZ WHERE

306

SPJZ.НОМЕР_ДЕТАЛИ = SPJY.НОМЕР_ДЕТ

АЛИ

AND SPJZ.НОМЕР_ПОСТАВЩИКА =

’S1’));

16. SELECT DISTINCT НОМЕР_ИЗДЕЛИЯ

FROM SPJ SPJX WHERE NOT EXISTS

(SELECT * FROM SPJ SPJY WHERE EXISTS

(SELECT * FROM SPJ SPJA WHERE

SPJA.НОМЕР_ПОСТАВЩИКА

= ’S1’

AND SPJA.НОМЕР_ДЕТАЛИ =

SPJY.НОМЕР_ДЕТ

АЛИ)

AND NOT EXISTS (SELECT * FROM SPJ SPJB WHERE

SPJB.НОМЕР_ПОСТАВЩИКА = ’S1’ AND SPJB.НОМЕР_ДETAЛИ =

SPJY.НОМЕР_ДЕТАЛИ AND SPJB.НОМЕР_ИЗДEЛИЯ =

SPJX.НОМЕР_ИЗДЕЛИЯ)

);

17. SELECT DISTINCT НОМЕР_ИЗДЕЛИЯ

FROM SPJ SPJX WHERE NOT EXISTS

(SELECT *

307

FROM SPJ SPJY

WHERE EXISTS (SELECT *

FROM SPJ SPJA WHERE

SPJA.НОМЕР_ДЕТАЛИ = SPJY.НОМЕ

Р_ДЕТАЛИ

AND SPJA.НОМЕР_ИЗДЕЛИЯ =

SPJX.НОМЕ Р_ИЗДЕЛИЯ)

AND NOT EXISTS (SELECT * FROM SPJ SPJB WHERE

SPJB.НОМЕР_ПОСТАВЩИКА

= ’S1’

AND SPJB.НОМЕР_ДЕТАЛИ = SPJY.НОМЕР_ДЕТАЛИ

AND SPJB.НОМЕР_ИЗДЕЛИЯ = SPJX.НОМЕР_ИЗДЕЛИЯ)

);

18. SELECT DISTINCT НОМЕР_ИЗДЕЛИЯ

FROM SPJ SPJX WHERE NOT EXISTS

(SELECT * FROM SPJ SPJY WHERE EXISTS

(SELECT * FROM SPJ SPJA WHERE

SPJA.НОМЕР_ПОСТАВЩИКА

=

SPJY.НОМЕ

308

Р_ПОСТАВЩИКА

AND SPJA.НОМЕР_ДЕТАЛИ IN

(SELECT

НОМЕР_ДЕТАЛИ

FROM P

WHERE ЦВЕТ =

’Красный’)

AND NOT EXISTS (SELECT * FROM SPJ SPJB WHERE

SPJB.НОМЕР_ПОСТАВЩИКА

=

SPJY.НОМЕР_ПО СТАВЩИКА

AND SPJB.НОМЕР_ИЗДЕЛИЯ = SPJX.НОМЕР_ИЗДЕЛИЯ)

));

Стандартные функции

19.Выдать общее число изделий, для которых поставляет детали поставщик S1.

20.Выдать общее количество деталей Р1, поставляемых поставщиком S1.

21.Для каждой поставляемой для некоторого изделия детали выдать ее номер, номер изделия и соответствующее общее количество деталей.

22.Выдать номера изделий, для которых город является первым в алфавитном списке таких городов.

23.Выдать номера изделий, для которых средний объем поставки деталей Р1 больше наибольшего объема поставки любой детали для изделия J1.

24.Выдать номера поставщиков, поставляющих деталь

309

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]