|
Программирование >> Руководство по sql
никакой потребности формировать группы. GROUP BY - в первом запросе - просто ошибка. Как вы, наверное, помните из предьщуших глав, GROUP BY имеет смысл пользоваться в основном с агрегирующими функциями (в этом случае вы можете находить итоговое значение для каждой группы). Вот как, например, можно было бы найти среднюю цену книг, стоимость которых не превышает $10.00, по типам этих книг: SQL: select avg{price), type from titles where price < $10.00 group by type Результат: price type 2.99 business 2.99 mod cook 7.50 psychology Возможно, tot пользователь, который отправил данный вопрос в Internet, представлял себе что-то вроде этого. GROUP BY в данном случае имеет смысл, поскольку в предложении SELECT есть афегирующая функция. Однако вернемся к первому вопросу: почему все-таки в результатах присутствуют сфоки для книг, цены на которые выше $10.00, в то время как, судя по всему, предложение WHERE должно было бы убрать их? Если проанализировать результаты первого и второго запросов, а также результаты запроса без предложений GROUP BY и HAVING, то можно, наверное, понять, в чем тут дело. Предложение WHERE нашло сфоки со значениями ниже $10.00. Они включают фи типа книг: business, modcook и psychology. Предложение GROUP BY затем отобразило все книги в каждой из указанных фупп. Если в этот запрос добавить ORDER BY, ситуация прояснится:
Запрос с предложением GROUP BY можно перефразировать как отобрази для меня цены и типы всех книг в группах, содержащих одну или несколько книг с ценами ниже $10.00 . Обратите внимание, что в результатах отсутствуют строки popular comp или trad cook. Нет здесь книг любой из этих групп, которые стоили бы ниже $10.00. Поскольку в списке выбора отсутствуют афегирующие функции, отображается каждая сфока, удовлетворяющая указанным критериям (а не одна сфока для итоговых значений каждой фуппы). Теперь перейдем ко второму вопросу: почему повторение условия WHERE в предложении HAVING исправляет результаты? Во-первых, WHERE находит дешевые книги, а затем GROUP BY вставляет все книги в фуппы, которые содержат одну или несколько дешевых книг. Наконец, HAVING выбирает в этом списке значения ниже $10.00. Поскольку условия WHERE и HAVING идентичны, вы получаете в конце концов те же четыре строки в результате выполнения запроса, содержащего только WHERE, и запроса, содержащего предложения WHERE, GROUP BY и HAVING. Можно было бы сказать, что HAVING в этом конкретном запросе отменяет действие GROUP BY. Изменение условия в предложении HAVING делает данный процесс более понятным: SQL: select price, type from titles where price < $10.00 group by type having price > $20.00 Результат: price type 21.59 psychology После того как WHERE классифицирует сфоки, и GROUP BY сформирует Фуппы, HAVING делает завершающий аккорд . Как вы уже видели, WHERE и GROUP BY вместе отображают одиннадцать сфок. HAVING убирает все эти сфо-ки, кроме одной, цена в которой превышает $20.00. Поскольку условия WHERE и HAVING различны, запрос с HAVING находит не те сфоки, которые находит запрос, содержащий только WHERE. В сущности, если рассмафивать этот конкретный запрос с его необычным использованием GROUP BY, то запрос, содержащий только HAVING, позволяет получить те же результаты, что и запрос, содержащий только WHERE, и даже запрос, содержащий и WHERE, и HAVING. SQL: select price, type from titles group by type having price < $10.00 Результат: price type 2.99 business 2.99 mod cook 7.00 psychology 7.99 psychology На самом деле ваша реализация может не допускать использования предложения HAVING без GROUP BY. Подробнее об использовании GROUP BY и HAVING вы можете узнать из справочного руководства по вашей системе. Наилучший способ избежать загадочных результатов, подобных указанным выше, - это тщательно проанализировать, чего именно вы хотите добиться с помощью того или иного запроса. Может оказаться (как в нашем случае), что в использовании GROUP BY нет никакой необходимости. Сочетание значений строк и агрегирующих функций Вот еще одна ситуация, связанная с использованием предложений GROUP BY и HAVING. Как вы, наверное, помните, есть ряд строгих ограничений на то, что разрешено помещать в списке выбора в случае использования предложения GROUP BY. Вообще говоря, вы ограничены столбцами, которые вы используете для фуппирования, и столбцами, для которых вы вычисляете групповые итоговые (агрегирующие) значения. В выходных результатах отображается фуппа и итоговое значение для фуппы. В некоторых системах предусмотрены расширения, которые допускают наличие в списке выбора дополнительных столбцов и выражений - значений, которые не являются ни группами, ни агрегирующими функциями. В этом разделе рассматриваются вопросы, которые могут возникнуть, когда вы работаете с такими комбинациями значений строк и групп. Если в вашей системе эти возможности не поддерживаются, переходите к разделу Как избежать проблем с предложением HAVING . Вот вопрос, который периодически возникает у пользователей: как найти итоговое значение для конкретного столбца каждой фуппы, а затем получить столбцы итоговых значений? В качестве отправной точки рассмофим ЬоокЫ1-версию такого запроса в его сокращенном варианте - для нахождения только минимальной цены (итогового значения) по каждому типу книг (фуппе): SQL: select type, min(price) as minprice from titles where type is not null group by type order by type Результат: type minprice popular comp 20.00 trad cook 11.95 business 2.99 psychology 7.00 mod cook 2.99 Распространенным подходом для получения итоговых и сфочных значений является добавление в список выбора неафегируемого столбца, такого как titlejd (уникального для каждой сфоки): SQL: select type, min(price) as minprice, title id from titles where type is not null group by type order by type
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |