Продвижение сайта по поисковым запросам, контекстная реклама, качественный копирайтинг и рерайтинг, создание сайта под ключ, QA процедуры и аудит в ИТ, бизнес анализ в Киеве, Украина.

Поиск

Админ

DISTINCT с подзапросами


DISTINCT с подзапросами

Вы можете в некоторых случаях использовать DISTINCT, чтобы вынудить подзапрос генерировать одиночное значение. Предположим, что мы хотим найти все Заказы для тех продавцов, которые обслуживают Hoffman (cnum = 2001). Имеется один способ, чтобы сделать это (вывод показывается в Рисунке 10.2):

SELECT *
FROM Orders
WHERE snum = (SELECT DISTINCT snum
FROM Orders
WHERE cnum = 2001);

===============  SQL Execution Log ==============
| SELECT *                                        |
| FROM Orders                                     |
| WHERE snum =                                    |
| (SELECT DISTINCT snum                           |
| FROM Orders                                     |
| Where cnum = 2001);                             |
| =============================================== |
|   onum       amt      odate      cnum     snum  |
|  -----   ---------  ---------   ------  ------- |
|   3003      767.19  10/03/1990   2001     1001  |
|   3008     4723.00  10/05/1990   2006     1001  |
|   3011     9891.88  10/06/1990   2006     1001  |
=================================================

Рисунок 10.2. Применение DISTINCT для получения одного значения из подзапроса.

Подзапрос установил, что значение поля snum совпало с Hoffman — 1001, и затем основной запрос выделил все Заказы с этим значением snum из таблицы Заказов (не разбирая, относятся они к Hoffman или нет). Так как каждый заказчик назначен к одному и только этому продавцу, мы знаем, что каждая строка в таблице Заказов с данным значением cnum должна иметь такое же значение snum. Однако, так как там может быть любое число таких строк, подзапрос мог бы вывести много (хотя и идентичных) значений snum для данного поля cnum. Аргумент DISTINCT предотвращает это. Если наш подзапрос возвратит более одного значения, это будет указывать на ошибку в наших данных — хорошая вещь для знающих об этом.

Альтернативный подход должен заключаться в том, чтобы ссылаться к таблице Заказчиков, а не к таблице Заказов в подзапросе. Так как поле cnum — это первичный ключ (о ключах см. в Главе 19) таблицы Заказчика, запрос выбирающий его, должен произвести только одно значение. Это рационально только если вы как пользователь имеете доступ к таблице Заказов, но не к таблице Заказчиков. В этом случае вы можете использовать решение, которое мы показали выше (SQL имеет механизмы, которые определяют, кто имеет привилегии, чтобы делать что-то в определенной таблице; это будет объясняться в Главе 22).

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

Предикаты с подзапросами являются необратимыми

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

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

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

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

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

SELECT *
FROM Orders
WHERE (SELECT DISTINCT snum
FROM Orders
WHERE cnum = 2001) = snum;

В строгой ANSI реализации, это приведет к неудаче, хотя некоторые программы и позволяют делать такие вещи  (в частности, в Interbase такой запрос работает). ANSI также предохраняет вас от появления обоих значений при сравнении, которые нужно вывести с помощью подзапроса.

Популярность: 5%




Оставить комментарий или два


Навигация

Блог / Главная / Разработка / DISTINCT с подзапросами

Инфо

Запись опубликовал admin 27 апреля 2010 года и разместил в рубрике Разработка.   Запись имеет метки:   К статье пока нет комментариев. Вы можете быть первым.  

Случайные записи

Специальный оператор ALL sql Объединения таблиц по равенству значений sql Что такое реляционная база данных Модифицирование представлений sql