Запрос, в котором используется импликация
Выдать номера поставщиков, поставляющих, по крайней мере, все те детали, которые поставляются поставщиком S2 (тот же самый запрос, что и в предыдущем примере).
В этом примере иллюстрируется еще одно очень полезное понятие — логическая импликация. Первоначальную задачу можно перефразировать следующим образом: «Выдать номера поставщиков, скажем, Sx, таких, что ДЛЯ ВСЕХ деталей Ру, если поставщик S2 поставляет деталь Ру, то поставщик Sx поставляет деталь Ру».
Выражение
IF р THEN q (ЕСЛИ р ТО q),
где р и q — предикаты, является предикатом логической импликации. Он определяется как эквивалент предиката:
NOT (р) OR q.
Иными словами, импликация «IF р THEN q» (читается также следующим образом: «из р СЛЕДУЕТ q») принимает значение ложь тогда и только тогда, когда q—ложь, а р— истина, как показывает табл. 8.5:
Таблица 8.5
Таблица истинности
р |
q |
IF р THEN q |
T |
T |
T |
T |
F |
F |
F |
T |
T |
F |
F |
T |
Многие формулировки задач на обычном языке весьма естественным образом выражаются в терминах логической импликации. Несколько примеров можно найти в конце данной части среди предлагаемых упражнений. Язык SQL непосредственно не поддерживает импликацию. Но предыдущее определение показывает, каким образом любой содержащий импликацию предикат может быть трансформирован в другой предикат, который ее не содержит.
281
Пусть, например, р представляет собой предикат «Поставщик S2 поставляет деталь Ру», а q — предикат «Поставщик Sx поставляет деталь Ру». Тогда предикат
IF р THEN q
эквивалентен предикату
NOT (поставщик S2 поставляет деталь Ру)
OR (поставщик Sx поставляет деталь Ру);
или в языке SQL:
NOT EXISTS (SELECT * FROM SP SPY
WHERE SPY.НОМЕР_ПОСТАВЩИКА = ’S2’) OR EXISTS
(SELECT * FROM SP SPZ
WHERE SPZ.НОМЕР_ПОСТАВЩИКА = Sx
AND SPZ.НОМЕР_ДЕТАЛИ = SPY.НОМЕР_ДЕТАЛИ)
Следовательно, предикат
FORALL Ру (IF р THEN q),
который эквивалентен предикату
NOT EXISTS Ру (NOT (IF р THEN q)),
т. e, предикату
NOT EXISTS Ру (NOT (NOT (р) OR q)),
может быть записан, таким образом, в виде:
NOT EXISTS Ру (р AND NOT (q)),
или в языке SQL:
NOT EXISTS (SELECT * FROM SP SPY
282
WHERE SPY.НОМЕР_ПОСТАВЩИКА = ’S2’
AND NOT EXISTS (SELECT * FROM SP SPZ
WHERE SPZ.НОМЕР_ПОСТАВЩИКА = Sx AND SPZ.НОМЕР_ДЕТАЛИ = SPY.НОМЕР_ДЕТАЛИ))
Поэтому полный запрос принимает вид:
SELECT DISTINCT НОМЕР_ПОСТАВЩИКА FROM SP SPX
WHERE NOT EXISTS (SELECT * FROM SP SPY
WHERE SPY.НОМЕР_ПОСТАВЩИКА = ’S2’ AND NOT EXISTS
(SELECT * FROM SP SPZ WHERE
SPZ.НОМЕР_ПОСТАВЩИКА = SPX.НОМЕР_ПОСТАВЩИКА
AND SPZ.НОМЕР_ДЕТАЛИ = SPY.НОМЕР_ДЕТАЛИ)):
Такой же вид имеет запрос выше. Таким образом, понятие импликации обеспечивает основу для систематического подхода к определенному классу (весьма сложных) запросов и их преобразованию в эквивалентную форму в языке SQL. Попрактиковаться в таком подходе позволяют упражнения в конце данной части.
Стандартные функции
Хотя и весьма мощное во многих отношениях, предложение SELECT в том виде, как оно было до сих пор описано, остается все еще неадекватным для многих
283
практических задач. Например, даже настолько простой запрос, как «Сколько имеется поставщиков?» нельзя выразить, используя только введенные до сих пор конструкции. Для того чтобы усилить его основные возможности по выборке данных, в SQL предусматривается ряд специальных стандартных функций. В настоящее время доступны функции COUNT (число значений), SUM (сумма), AVG (среднее), МАХ (максимум) и MIN (минимум). Кроме специального случая «COUNT (*)» (см. ниже) каждая из этих функций оперирует совокупностью значений в одном столбце некоторой таблицы, возможно, производной, т. e. сконструированной некоторым образом из заданных базовых таблиц, и продуцирует в качестве ее результата единственное значение, определенное следующим образом:
COUNT — число значений в столбце
SUM — сумма значений по столбцу
AVG — среднее значение в столбце
МАХ — самое большое значение в столбце MIN — самое малое значение в столбце
Для функций SUM и AVG рассматриваемый столбец должен содержать числовые значения. В общем случае аргументу функции может факультативно предшествовать ключевое слово DISTINCT (различный), указывающее, что избыточные дублирующие значения должны быть исключены перед тем, как будет применяться функция. Однако для функций МАХ и MIN ключевое слово DISTINCT не имеет отношения к делу и должно быть опущено. Для функции COUNT ключевое слово DISTINCT должно быть специфицировано. Специальная функция COUNT (*), для которой использование DISTINCT не допускается, предусмотрена для подсчета всех строк в таблице без исключения каких-либо дубликатов. Если DISTINCT специфицируется, то аргумент должен состоять только из имени столбца, например ВЕС. Если DISTINCT не специфицировано, аргумент может представлять собой арифметическое выражение, например ВЕС*454.
284
В столбце-аргументе всегда перед применением функции исключаются все неопределенные значения, независимо от того, специфицировано ли DISTINCT, за исключением случая COUNT (*), при котором неопределенные значения обрабатываются точно так же, как и значения, не являющиеся неопределенными. Если оказывается, что аргумент
— пустое множество, функция COUNT принимает значение нуль. Все другие функции принимают в этом случае неопределенное значение.
Функция во фразе select
Выдать общее количество поставщиков.
SELECT COUNT (*)
FROM S;
Результат:
5
Функция во фразе select со спецификацией distinct
Выдать общее количество поставщиков, поставляющих в настоящее время детали:
SELECT COUNT (DISTINCT НОМЕР_ПОСТАВЩИКА) FROM SP;
Результат:
4
Функция во фразе select с предикатом
Выдать количество поставок для детали Р2.
SELECT COUNT (*)
FROM SP
WHERE НОМЕР_ДЕТАЛИ = ’Р2’;
Результат:
4
285