Выдать номера поставщиков, которые поставляют по крайней мере все те детали, которые поставляет поставщик S2.
Один из способов справиться с этой сложной задачей состоит в том, чтобы разбить ее на множество более простых запросов и заниматься ими последовательно. Так, можно сначала определить множество номеров деталей, которые поставляются поставщиком S2:
SELECT НОМЕР_ДЕТАЛИ
FROM SP
WHERE НОМЕР_ПОСТАВЩИКА = 'S2';
Результат:
НОМЕР_ДЕТАЛИ |
Р1 Р2 |
Используя предложения CREATE TABLE и INSERT, которые будут обсуждаться в главе 6, можно сохранить этот результат в некоторой таблице в базе данных, например в таблице ВРЕМЕННАЯ. Далее можно перейти к определению множества номеров поставщиков, которые поставляют все детали, перечисленные в таблице ВРЕМЕННАЯ (очень похоже на пример 5.3.3):
SELECT DISTINCT НОМЕР_ПОСТАВЩИКА
FROM SP SPX
WHERE NOT EXISTS
(SELECT *
FROM ВРЕМЕННАЯ
WHERE NOT EXISTS
(SELECT *
FROM SP SPY
WHERE SPY.НОМЕР_ПОСТАВЩИКА =
SPX. НОМЕР_ПОСТАВЩИКА
AND SPY. НОМЕР_ДЕТАЛИ=
ВРЕМЕННАЯ. НОМЕР_ДЕТАЛИ));
Результат:
НОМЕР_ПОСТАВЩИКА |
S1 S2 |
(Заметим, однако, что этот запрос отличается от запроса в примере 5.4.3 необходимостью использовать по крайней мере один псевдоним, поскольку мы выделяем значения столбца НОМЕР_ПОСТАВЩИКА из таблицы SP, а не значения столбца ФАМИЛИЯ из таблицы S. По этой причине необходимо иметь возможность одновременно делать две различные ссылки на таблицу SP.)
Теперь таблица ВРЕМЕННАЯ может быть уничтожена. Идея о том, чтобы справляться со сложными запросами таким пошаговым образом для легкости понимания, часто оказывается полезной. Однако можно также выразить рассматриваемый полный запрос в виде единственного предложения SELECT, полностью исключая при этом необходимость в таблице ВРЕМЕННАЯ:
SELECT DISTINCT НОМЕР_ПОСТАВЩИКА
FROM SP SPX
WHERE NOT EXISTS
(SELECT *
FROM SP SPY
WHERE НОМЕР_ПОСТАВЩИКА ='S2'
AND NOT EXISTS
(SELECT *
FROM SP SPZ
WHERE SPZ.НОМЕР_ПОСТАВЩИКА =
SPX. НОМЕР_ПОСТАВЩИКА
AND SPZ. НОМЕР_ДЕТАЛИ=
SPY. НОМЕР—ДЕТАЛИ));