|
Программирование >> Хронологические базы данных
зультате чего такой запрос, как Получить среднее итоговое количество деталей , нельзя сформулировать без громоздких выражений. Если быть точным, то следующий запрос ***НЕКОРРЕКТЕН***. SELECT AVG (SUM (SP.QTY) ) ~ Внимание! Это ошибка! FROM SP; Вместо этого данный запрос следовало бы сформулировать, например, так. SELECT AVG ( X ) FROM ( SELECT SUM ( SP.QTY ) AS X FROM SP GROUP BY SP.SI ) AS POINTLESS ; Назначение предложения GROUP BY разъясняется в следующем примере, а использование вложенных подзапросов - несколько ниже. Стоит отметить, что возможность вложения подзапросов в предложение WHERE, как было сделано в этом примере, появилась только в стандарте SQL/92 и еще не используется достаточно широко. Замечание. Спецификация AS POINTLESS бессмысленна, однако ее наличия требуют синтаксические правила языка SQL (приложение А). 7.7.8. Для каждой поставляемой детали указать номер и общий объем поставки в штуках SELECT SP.PI, SUM ( SP.QTY ) AS TOTQTY FROM SP GROUP BY SP.PI ; В языке SQL это выражение является аналогом такого выражения реляционной алгебры. SUMMARIZE SP PER SP { Р# } ADD SUM ( QTY ) AS TOTQTY Oho также является аналогом следующего выражения реляционного исчисления кортежей. ( SPX.PI, SUM ( SPY WHERE SPY.P* = SPX.PI, QTY ) AS TOTQTY ) В частности, стоит отметить, что если в запросе указано предложение GROUP BY, то выражения в предложении SELECT должны быть однозначными для заданной группы. Вот альтернативная, а также более предпочтительная формулировка того же запроса. SELECT Р.PI, ( SELECT SUM ( SP.QTY ) FROM SP WHERE SP.PI = P.PI ) AS TOTQTY FROM P ; Возможность использования вложенных подзапросов для представления скалярных элементов (например, в предложении SELECT, как здесь) была добавлена в стандарт SQL/92 и является важнейшим усовершенствованием по сравнению с первоначальным вариантом языка SQL. В рассматриваемом примере это предоставляет возможность генерировать результат, который включает строки для деталей, не поставляемых со- всем, а предыдущая формулировка (использующая предложение GROUP BY) этого не позволяла. (Однако значение TOTQTY для таких деталей будет, к сожалению, представлено как NULL-значение, а не нуль.) 7.7.9. Указать номера всех типов деталей, поставляемых более чем одним поставщиком SELECT SP.PI FROM SP GROUP BY SP.PI HAVING COUNT ( SP.Sl ) > 1 ; Предложение HAVING в отношении групп является тем же, что и предложение WHERE для обычных строк. Другими словами, предложение HAVING используется для исключения групп аналогично тому, как предложение WHERE используется для исключения отдельных строк. Выражение в предложении HAVING должно быть однозначным для заданной группы. 7.7.10. Определить имена поставщиков детали с номером Р2 SELECT DISTINCT S.SNAME FROM S WHERE S.SI IN ( SELECT SP.Sl FROM SP WHERE SP.PI = P2 ) ; Пояснения. В этом примере в предложении WHERE используется так называемый подзапрос. Проще говоря, подзапрос- это выражение из предложений SELECT-FROM-WHERE-GROUP BY-HAVING, которое вложено в другое такое же выражение. Подзапрос чаще всего используется для представления множества значений, поиск которых осуществляется с помощью предложения IN условие, что и представлено в данном в примере. Система вычисляет запрос в целом, предварительно вычислив указанный подзапрос (по крайней мере, концептуально). Подзапрос в данном примере возвращает множество номеров поставщиков детали с номером Р2: {S1, S2, S3, S4}. Таким образом, первоначальное выражение эквивалентно следующему, более простому, SELECT DISTINCT S.SNAME FROM S WHERE S.SI IN ( SI, S2, S3, S4 ) ; Стоит отметить, что первоначальную задачу - Получить имена поставщиков детали с номером Р2 - можно равносильно выразить с помощью операции соединения, например, так. SELECT DISTINCT S.SNAME FROM S, SP WHERE S.SI = SP.Sl AND SP.PI = P2 ; 7.7.11. Определить имена поставщиков по крайней мере одной красной детали SELECT DISTINCT S.SNAME FROM S WHERE S.S# IN ( SELECT SP.SI FROM SP WHERE SP.PI = IN ( SELECT P.P# FROM P WHERE P.COLOR = Red ) ) ; Подзапросы могут иметь произвольную глубину вложения. Упражнение. Приведите эквивалентную формулировку этого запроса с использованием операции соединения. 7.7.12. Указать номера поставщиков, статус которых меньше текущего максимального статуса в таблице S SELECT S.SI FROM S WHERE S.STATUS < ( SELECT MAX ( S.STATUS ) FROM S ) ; В этом примере используются две отдельные неявные переменные кортежей, обозначенные одним и тем же именем S и изменяющиеся на таблице S. 7.7.13. Указать имена поставщиков детали с номером Р2 Замечание. Этот пример повторяет пример 7.7.10. Ниже приводится другое решение для того, чтобы представить еще одно средство языка SQL. SELECT DISTINCT S.SNAME FROM S WHERE EXISTS ( SELECT * FROM SP WHERE SP.SI = S.S# AND SP.PI = P2 ) ; Яоясне ме. SQL-выражение EXISTS (SELECT ... FROM ...) будет иметь значение мстм-на тогда и только тогда, когда результат вычисления выражения SELECT ... FROM ... будет непустым. Другими словами, в языке SQL функция EXISTS соответствует квантору существования реляционного исчисления [18.6].
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |