Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УМП-БД.doc
Скачиваний:
18
Добавлен:
05.12.2018
Размер:
1.26 Mб
Скачать

Ограничения на запросы с группировкой

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

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

константа,

агрегатная функция, возвращающая одно значение для всех строк, входящих в группу;

столбец группировки, который, по определению, имеет одно и то же значение во всех строках группы;

выражение, включающее в себя перечисленные выше элементы.

На практике в список возвращаемых столбцов запроса с группировкой всегда входят столбец группировки и агрегатная функция. Если последняя не указана, значит, запрос можно более просто выразить с помощью ключевого слова distinct без использования предложения group by. И наоборот, если не включить в результаты запроса столбец группировки, вы не сможете определить, к какой группе относится каждая строка результатов!

Еще одно ограничение запросов с группировкой обусловлено тем, что в SQL игнорируется информация о первичных и внешних ключах при анализе правильности запроса с группировкой. Рассмотрим следующий запрос:

Зная природу данных, можно сказать, что запрос правильный, поскольку группировка по идентификатору служащего — фактически то же самое, что и группировка по имени служащего. Говоря более точно, столбец группировки empl_num является первичным ключом таблицы salesreps, поэтому столбец name должен иметь одно значение для каждой группы. Тем не менее выдается сообщение об ошибке, поскольку столбец name не указан в качестве столбца группировки. Чтобы решить эту проблему, необходимо просто включить этот столбец в предложение group by:

Конечно, если идентификатор служащего в результатах запроса не требуется, можно вообще исключить его из списка возвращаемых столбцов:

ЗНАЧЕНИЯ NULL В СТОЛБЦАХ ГРУППИРОВКИ

Когда в столбце группировки содержится значение null, возникают дополнительные осложнения. Если значение столбца неизвестно, к какой группе его следует отнести? В предложении where при сравнении двух значений null результат имеет значение null (а не true), т.е. два значения null не считаются одинаковыми. Если такое соглашение применить в предложении group by, это приведет к тому, что каждая строка со значением null в столбце группировки будет помещена в отдельную группу, состоящую из одной этой строки.

На практике это правило очень неудобно. Поэтому в стандарте ANSI/ISO определено, что два значения null в предложении group by равны. Если две строки имеют значение null в одинаковых столбцах группировки и идентичные значения во всех остальных столбцах группировки, они помещаются в одну группу. Небольшая таблица иллюстрирует принцип обработки значений null предложением group by в соответствии со стандартом ANSI/ISO, как показано в следующем запросе:

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

УСЛОВИЯ ПОИСКА ГРУПП (ПРЕДЛОЖЕНИЕ HAVING)

Точно так же, как предложение where используется для отбора отдельных строк, участвующих в запросе, предложение having можно применить для отбора групп строк. Его формат соответствует формату предложения where. Предложение having состоит из ключевого слова having, за которым следует условие поиска. Таким образом, данное предложение oпpeдeляe условие поиска для групп.

Следующий пример иллюстрирует роль предложения having:

Вначале предложение group by разделяет заказы на группы по служащим. После того предложение having исключает все группы, в которых общая стоимость заказа не превышает $30000. И, наконец, предложение select вычисляет среднюю стоимость заказа для каждой из оставшихся групп и генерирует таблицу результатов запроса.

В предложении having указываются точно такие же условия поиска, что и в предложении where. Ниже приведен еще дин пример использования условия поиска групп:

В соответствии с этими правилами, SQL выполняет приведенный выше запрос таким образом:

1. Объединяет таблицы offices и salesreps, чтобы определить город, в котором работает служащий.

2. Группирует строки объединенной таблицы по офисам.

3. Исключает группы, содержащие две или менее строки — это те строки, которые не удовлетворяют критерию предложения having.

4. Вычисляет общие плановые и фактические объемы продаж для каждой группы.

Чтобы осуществить этот запрос, SQL выполняет следующие действия:

1. Объединяет таблицы orders и products, чтобы получить описание, цену и количество единиц на складе для каждого заказанного товара.

2. Группирует строки объединенной таблицы по идентификатору производителя и товара.

3. Исключает группы, в которых количество заказанных единиц составляет менее 75 процентов от количества на складе.

4. Вычисляет общее количество заказанных единиц для каждой группы.

5. Генерирует одну итоговую строку запроса для каждой группы.

6. Сортирует результаты запроса таким образом, чтобы товары, которых на складе больше, шли первыми.

Как было сказано ранее, столбцы description, price и qty_on_hand должны быть указаны в качестве столбцов группировки, поскольку они перечислены в списке возвращаемых столбцов. Однако на деле они не участвуют в процессе группировки, поскольку столбцы mfr_id и prouct_id полностью определяют строку таблицы products, и три оставшихся столбца автоматически имеют в группе одно значение.

Ограничения на условия поиска групп

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

  • константа',

  • агрегатная функция, возвращающая одно значение для всех строк, входящих в группу; I

  • столбец группировки, который, по определению, имеет одно и то же значение во всех строках труппы;

  • выражение, включающее в себя перечисленные выше элементы.

На практике условие поиска предложения having всегда должно включать в себя как минимум одну агрегатную функцию. Если это не так, условие поиска можно переместить в предложение where. Чтобы определить, где следует указать условие поиска — в предложении where или having, необходимо вспомнить, как применяются эти предложения:

  • предложение where применяется к отдельным строкам, поэтому выражения, содержащиеся в нем, должны вычисляться для отдельных строк;

  • предложение having применяется к группам строк, поэтому выражения, содержащиеся в нем, должны вычисляться для групп строк.

Значения NULL и условия поиска групп

Как и условие поиска в предложении where, условие поиска в предложении having может дать один из следующих результатов:

Если условие поиска имеет значение true, группа строк остается и для нее генерируется одна строка в результатах запроса.

Если условие поиска имеет значение false, группа строк исключается, и строка в результатах запроса для нее не генерируется.

Если условие поиска имеет значение null, группа строк исключается, и строка в результатах запроса для нее не генерируется.

Правила обработки значений null в условиях поиска для предложения having точно такие же, как и для предложения where

Предложение HAVING без GROUP BY

Предложение having почти всегда используется в сочетании с предложением group by, однако синтаксис оператора select не требует этого. Если предложение having используется без предложения group by, SQL рассматривает полные результаты запроса как одну группу. Другими словами, агрегатные функции, содержащиеся в предложении having, применяются к одной и только одной группе, и эта группа состоит из всех строк. На практике предложение having очень редко используется без соответствующего предложения group by.