Скачиваний:
25
Добавлен:
01.04.2014
Размер:
761.34 Кб
Скачать

114 Понимание sql

______________________________________________________________________

ГЛ. 10

Альтернативный подход должен быть чтобы ссылаться к таблице Заказчиков

а не к таблице Порядков в подзапросе. Так как поле cnum - это первич-

ный ключ таблицы Заказчика, запрос выбирающий его должен произвести

только одно значение. Это рационально только если вы как пользователь

имеете доступ к таблице Порядков но не к таблице Заказчиков. В этом случае,

вы можете использовать решение которое мы показали выше. ( SQL имеет

механизмы которые определяют - кто имеет привилегии чтобы делать что-то

в определенной таблице. Это будет объясняться в Главе 22.)

Пожалуйста учтите, что методика используемая в предшествующем примере

применима только когда вы знаете, что два различных поля в таблице должны

всегда совпадать, как в нашем случае. Эта ситуация не является типичной в ре-

ляционных базах данных, она являеться исключением из правил.

ПРЕДИКАТЫ С ПОДЗАПРОСАМИ ЯВЛЯЮТСЯ НЕОБРАТИМЫМИ

Вы должны обратить внимание что предикаты включающие подзапросы,

используют выражение

< скалярная форма > < оператор > < подзапрос >,

а, не

< подзапрос > < оператор > < скалярное выражение >

или,

< подзапрос > < оператор > < подзапрос >.

Другими словами, вы не должны записывать предыдущий пример так:

SELECT *

FROM Orders

WHERE ( SELECT DISTINCT snum

FROM Orders

WHERE cnum = 2001 )

= snum;

В строгой ANSI реализации, это приведет к неудаче, хотя некоторые программы

и позволяют делать такие вещи. ANSI также предохраняет вас от появления

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

ИСПОЛЬЗОВАНИЕ АГРЕГАТНЫХ ФУНКЦИЙ В ПОДЗАПРОСАХ

Один тип функций, который автоматически может производить одиночное

значение для любого числа строк, конечно же, - агрегатная функция.

РАЗМЕЩЕНИЕ ЗАПРОСОВ ВНУТРИ ДРУГА ДРУГА 115

______________________________________________________________________

Любой запрос использующий одиночную функцию агрегата без предложения

GROUP BY будет выбирать одиночное значение для использования в основном

предикате. Например, вы хотите увидеть все порядки имеющие сумму приоб-

ретений выше средней на 4-е Октября ( вывод показан на Рисуноке 10.3 ):

SELECT *

FROM Orders

WHERE amt >

( SELECT AVG (amt)

FROM Orders

WHERE odate = 10/04/1990 );

=============== SQL Execution Log ==============

| |

| SELECT * |

| FROM Orders |

| WHERE amt > |

| (SELECT AVG (amt) |

| FROM Orders |

| WHERE odate = 01/04/1990 ); |

| =============================================== |

| onum amt odate cnum snum |

| ----- -------- ---------- ----- ----- |

| 3002 1900.10 10/03/1990 2007 1004 |

| 3005 2345.45 10/03/1990 2003 1002 |

| 3006 1098.19 10/03/1990 2008 1007 |

| 3009 1713.23 10/04/1990 2002 1003 |

| 3008 4723.00 10/05/1990 2006 1001 |

| 3010 1309.95 10/06/1990 2004 1002 |

| 3011 9891.88 10/06/1990 2006 1001 |

================================================

Рисунок 10.3: Выбор всех сумм со значением выше средней на 10/04/1990

Средняя сумма приобретений на 4 Октября - 1788.98 ( 1713.23 + 75.75)

делится пополам, что в целом равняется = 894.49. Все строки со значением в

поле amt выше этого - являются выбраными.

Имейте ввиду что сгруппированные агрегатные функции, которые являются

агрегатными функциями определенными в терминах предложения GROUP BY,

могут производить многочисленые значения. Они, следовательно, не позволи-

тельны в подзапросах такого характера. Даже если GROUP BY и HAVING

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

подзапроса, команда будет отклонена в принципе. Вы должны использовать

Соседние файлы в папке ПОНИМАНИЕ SQL