By group pl sql: Oracle / PLSQL: GROUP BY Clause
Oracle ПЛ/SQL — лучший способ сделать выбор, группа-с, того-С, где-положение о различных столбцов, в зависимости от условия?
Привет, у меня есть проблема, которая требует, чтобы я сделал выбор для разных столбцов, основываясь на условии. Я могу достичь этого в сохраненном proc с нечистым предложением IF ELSIF, но я хотел бы знать лучший способ решить эту проблему. Вот пример, чтобы сделать его более ясным:
PROCEDURE notSoSmartSelect(type IN VARCHAR, a_filter IN VARCHAR
, b_filter IN VARCHAR, results OUT SYS_REFCURSER) IS
BEGIN
IF type = 'A' THEN
OPEN results FOR
SELECT a, sum(val) v FROM sample_table
GROUP BY a, ORDER BY a;
ELSIF type = 'B' THEN
OPEN results FOR
SELECT b, a, sum(val) v FROM sample_table
WHERE a = a_filter
GROUP BY b, a, ORDER BY a, b;
ELSIF type = 'C' THEN
OPEN results FOR
SELECT c, b, a, sum(val) v FROM sample_table
WHERE a = a_filter AND b = b_filter
GROUP BY c, b, a, ORDER BY a, b, c;
END IF;
END;
Как вы уже заметили, в каждом случае используется одна и та же таблица, но для выборки, фильтрации, группировки и упорядочения используются разные столбцы.
Приведенный выше код выглядит довольно просто, но фактическая проблема имеет много ветвей и имеет несколько if-else, что делает код очень грязным. Есть ли элегантный и чистый способ подойти к этому? Может Быть, Динамический SQL? Но я, кажется, не могу понять, как лучше всего написать dynamic sql для этого. Заранее спасибо.
oracle
plsql
dynamic-sql
Поделиться
Источник
Ocelot
22 июня 2016 в 06:59
2 ответа
- Языков в зависимости от того, в JPA/SQL
Я использую Hibernate в качестве поставщика JPA с именованными запросами и задаюсь вопросом, есть ли родной способ упорядочить результаты в зависимости от языка. Базовая база данных-это какой-то Oracle R10. Допустим, у вас есть таблица животных, которая имеет столбец английского имени и столбец…
- «Двойная группа по» в Oracle SQL?
Когда я изучал утверждения SQL, я столкнулся с одним примером (относительно демо — базы данных SCOTT), и я понятия не имею, как его решить. В каком отделе(отделах) присутствуют все салграды? Мой самый многообещающий подход состоит в том, чтобы сгруппировать все salgrades и отделы в Объединенных…
1
Я не считаю это «unclean». Запросы сильно отличаются друг от друга, поэтому я бы не стал пытаться объединить их в один оператор.
Но учитывая, что они настолько различны (разные выбранные столбцы, разные группы агрегации, разные предложения where), почему все они находятся в одной процедуре? Я бы сделал это три процедуры, если таковые имеются; вероятно, скорее три вида.
Поделиться
Thorsten Kettner
22 июня 2016 в 07:27
0
Это гораздо яснее, чем динамический подход sql, который вы хотели бы попробовать. Как уже упоминалось, у вас есть много ветвей IF ELSE, и было бы очень утомительно даже построить такое количество и "TEST"
таких условий.
На мой взгляд, ваш refcursor
используется любым фронтальным приложением, таким как JAVA
, поэтому лучше RETURN весь вывод, а затем выполнять все манипуляции с этого конца.
Поделиться
Avrajit Roy
22 июня 2016 в 07:41
Похожие вопросы:
Лучший способ перенести export/import с SQL Server на oracle
Я столкнулся с необходимостью доступа для отчетности к некоторым данным, которые живут в Oracle, и другим данным, которые живут в базе данных SQL Server 2000. По разным причинам они живут по разные…
Лучший способ сделать вложенную логику оператора case в SQL Server
Я пишу запрос SQL, где несколько возвращаемых столбцов должны быть вычислены в зависимости от довольно большого количества условий. В настоящее время я использую вложенные операторы case, но это…
MySQL/PDO: выбор различных столбцов в зависимости от параметров
У меня есть запрос MySQL, который должен изменяться в зависимости от того, какие параметры ему передаются. Звучит достаточно просто, не так ли? Проблема в том, что если параметр равен ‘0’, то мне…
Языков в зависимости от того, в JPA/SQL
Я использую Hibernate в качестве поставщика JPA с именованными запросами и задаюсь вопросом, есть ли родной способ упорядочить результаты в зависимости от языка. Базовая база данных-это какой-то…
«Двойная группа по» в Oracle SQL?
Когда я изучал утверждения SQL, я столкнулся с одним примером (относительно демо — базы данных SCOTT), и я понятия не имею, как его решить. В каком отделе(отделах) присутствуют все салграды? Мой…
CSS речевые пузыри: как обновить положение наконечника в зависимости от того, где находится пузырь
http://jsfiddle.net/9ZtK2 / У меня есть значок изображения и речевой пузырь рядом с ним, чтобы сделать его похожим на говорящего. Положение наконечника находится слева. .text_bubble_right {…
Получение результирующего набора с помощью процедуры oracle
У меня очень ограниченные навыки по pl-sql, и у меня очень сложная ситуация. В mssql у меня есть процедура, которая возвращает результирующий набор с различным количеством столбцов из различных…
Oracle SQL извлечения столбцов в зависимости от условий все в той же таблице
У меня есть представление Oracle, которое нужно использовать для заполнения различных имен на странице. Имена страниц заполняются на основе критериев поиска с использованием тех же столбцов базы…
Oracle PL/SQL for loop: выберите запрос в зависимости от условия
У меня есть тело процедуры с циклом на результатах запроса: for src in ( /* query A */ ) loop /* * loop body… */ end loop; Но мне нужно выбрать между двумя или более различными запросами а в…
сумма столбцов в sql в зависимости от условия
Я хочу суммировать значения столбцов в зависимости от следующего условия USERID | QUERYID | UPVOTE | DOWNVOTE 1 | 15 | 1 | 0 0 | 15 | 0 | -1 6 | 15 | 0 | -1 1 | 7 | 1 | 0 8 | 7 | 1 | 0 Мне интересно…
Оператор SQL GROUP BY: синтаксис, примеры
Оператор SQL GROUP BY используется для объединения результатов выборки по одному или нескольким столбцам.
Оператор SQL GROUP BY имеет следующий синтаксис:
GROUP BY column_name
С использованием оператора SQL GROUP BY тесно связано использование агрегатных функций и оператор SQL HAVING
Примеры оператора SQL GROUP BY. Имеется следующая таблица Artists:
Singer | Album | Year | Sale |
The Prodigy | Invaders Must Die | 2008 | 1200000 |
Drowning Pool | Sinner | 2001 | 400000 |
Massive Attack | Mezzanine | 1998 | 2300000 |
The Prodigy | Fat of the Land | 1997 | 600000 |
The Prodigy | Music For The Jilted Generation | 1994 | 1500000 |
Massive Attack | 100th Window | 2003 | 1200000 |
Drowning Pool | Full Circle | 2007 | 800000 |
Massive Attack | Danny The Dog | 2004 | 1900000 |
Drowning Pool | Resilience | 2013 | 500000 |
Пример 1. Используя оператор SQL GROUP BY найти сумму продаж альбомов (Sale) всех исполнителей (Singer):
SELECT Singer, SUM(Sale) AS AllSales FROM Artists GROUP BY Singer
Результат:
Singer | AllSales |
Drowning Pool | 1700000 |
Massive Attack | 5400000 |
The Prodigy | 3300000 |
В данном запросе используется оператор SQL AS, позволяющий задать новое имя столбца AllSales на выходе. В нашем случае это сделано для наглядности.
Пример 2. Узнать в каком году был выпущен последний альбом каждой из групп используя оператор SQL GROUP BY:
SELECT Singer, MAX(Year) AS LastAlbumYear FROM Artists GROUP BY Singer
Результат:
Singer | LastAlbumYear |
Drowning Pool | 2013 |
Massive Attack | 2004 |
The Prodigy | 2008 |
Недопустимые Запросы с Использованием Групповых Функций
Любой столбец или выражение в списке SELECT
, который не является агрегатной функцией, должен быть в предложении GROUP BY
:
Всякий раз, когда Вы используете смесь отдельных элементов (DEPARTMENT_ID
) и групповые функции (COUNT
) в том же самом операторе SELECT
, следует включать предложение GROUP BY
, которое будет указывать отдельные элементы (в этом случае, DEPARTMENT_ID
). Если предложение GROUP BY
отсутствует, появляется сообщение об ошибке “not a single-group group function” и звездочка (*
) указывает незаконный столбец. Можно исправить ошибку в первом примере на рисунке, добавляя предложение GROUP BY
:
SELECT department_id, count(last_name) |
Любой столбец или выражение в списке SELECT
, который не находится в агрегатной функции, должен быть включен в предложение GROUP BY
. Во втором примере на рисунке job_id не состоит в предложении GROUP BY и не используется групповой функцией, таким образом возникает ошибка “not a GROUP BY expression”. Можно исправить ошибку во втором примере рисунка, включая job_id в предложение GROUP BY
.
SELECT department_id, job_id, COUNT(last_name) |
Некорректные Запросы с Использованием Групповых Функций
Нельзя использовать предложение
WHERE
, чтобы ограничить группы.Вы используете предложение
HAVING
для ограничения групп.Нельзя использовать групповые функции в предложении
WHERE
.
Предложение WHERE
не может использоваться, чтобы ограничить группы. Оператор SELECT
в примере на рисунке приводит к ошибке, потому что он использует предложение WHERE
, чтобы ограничить вывод средних зарплат теми отделами, у которых средняя зарплата больше чем $8,000
.
Однако, можно исправить ошибку в примере при использовании предложения HAVING
, чтобы ограничить группы:
SELECT department_id, AVG(salary) |
Далее: Создание Тройных Соединений с Предложением ON
Группировка по нескольким столбцам
Группировка по нескольким столбцам
Группировка
по нескольким столбцам
В предложениях GROUP BY можно
указывать столько столбцов, сколько вам необходимо, разделяя имена
элементы
списка запятыми. Таким образом, путем группировки одновременно по
нескольким
элементам можно создавать группы внутри групп. Каждый элемент из списка
GROUP
BY должен обязательно присутствовать в списке выбора —
другими словами,
группировать можно только выбираемые элементы.
Пример
SQL:
SELECT region, sex, COUNT(*) AS num_clients
FROM tbl_clients
GROUP BY
region, sex
Результат:
region | sex | num_clients |
California | f | 18 |
California | m | 15 |
Los Angeles | f | 42 |
Los Angeles | m | 57 |
New Jersey | f | 12 |
New Jersey | m | 21 |
New York | f | 15 |
New York | m | 18 |
Oregon | f | 15 |
Oregon | m | 18 |
Portland | f | 12 |
Portland | m | 32 |
Seattle | f | 37 |
Seattle | m | 40 |
Washington | f | 21 |
Washington | m | 11 |
Сначала строки таблицы разделяются
по городам, а затем каждая полученная группа разделяется по полу
клиента. В
результате получается 16 групп, или наборов. После этого к каждому
такому
набору применяется агрегирующая функция, которая вычисляет для каждого
города
количество клиентов женского и мужского пола.
Агрегация (конкатенация) строковых значений полей с группировкой
Иногда необходимо склеить (сконкатенировать) строковые значения полей возвращаемых запросом в одно значение в соответствии с группировкой по другому полю, сделать это можно как с помощью встроенных Oracle функций так и с помощью своей.
Ниже описание одного способа с использованием встроенной функции wm_concat и ссылки на описание остальных методов.
Имеем следующие входные данные:
Base Data: DEPTNO ENAME ---------- ---------- 20 SMITH 30 ALLEN 30 WARD 20 JONES 30 MARTIN 30 BLAKE 10 CLARK 20 SCOTT 10 KING 30 TURNER 20 ADAMS 30 JAMES 20 FORD 10 MILLER Desired Output: DEPTNO EMPLOYEES ---------- -------------------------------------------------- 10 CLARK,KING,MILLER 20 SMITH,FORD,ADAMS,SCOTT,JONES 30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD
Если вы используете Oracle 11g Release 2, то вместо недокументированной и официально не поддерживаемой WM_Concat можно использовать вполне легальную ListAGG, считая, что ее нет? делаем так:
COLUMN employees FORMAT A50 SELECT deptno, wm_concat(ename) AS employees FROM emp GROUP BY deptno; DEPTNO EMPLOYEES ---------- -------------------------------------------------- 10 CLARK,KING,MILLER 20 SMITH,FORD,ADAMS,SCOTT,JONES 30 ALLEN,BLAKE,MARTIN,TURNER,JAMES,WARD 3 rows selected.
Получили список сотрудников сгруппированных по отделу в строку через запятую. Основное отличие от оригинальной listagg, в невозможности задать символ разделителя.
Источники:
Запись опубликована 29.08.2011 в 8:57 дп и размещена в рубрике Ask Tom. Вы можете следить за обсуждением этой записи с помощью ленты RSS 2.0.
Можно оставить комментарий или сделать обратную ссылку с вашего сайта.
Предложение GROUP BY
Предложение GROUP BY, часть SelectExpression, групп
результат в подмножества, которые имеют совпадающие значения для одного или нескольких столбцов. В
в каждой группе нет двух строк, которые имеют одинаковое значение для столбца или столбцов группировки.
NULL считаются эквивалентными для целей группировки.
Обычно вы
используйте предложение GROUP BY вместе с агрегатным выражением.
Используя синтаксис ROLLUP, вы можете указать, что несколько уровней группировки
следует вычислить сразу.
Синтаксис
ГРУППА ПО { Имя столбца [, Имя столбца ] * | ROLLUP ( имя столбца [, имя столбца ] *) }
Имя столбца должно быть столбцом из
текущий объем запроса; в блоке запроса не может быть столбцов
вне текущей области. Например, если предложение GROUP BY находится в подзапросе,
он не может ссылаться на столбцы во внешнем запросе.
SelectItems дюйма
SelectExpression с
Предложение GROUP BY должно содержать только агрегаты или группирующие столбцы.
Примеры
- найти среднее время полета рейсов, сгруппированных по - аэропорт ВЫБРАТЬ СРЕДНЕЕ (время полета), orig_airport ОТ Рейсы ГРУППА ПО orig_airport ВЫБРАТЬ МАКС. (Название города), регион ИЗ городов, стран ГДЕ Cities.country_ISO_code = Country.country_ISO_code ГРУППА ПО РЕГИОНАМ - группа по маленькому ВЫБЕРИТЕ ID, СРЕДНЕЕ (ЗАРПЛАТА) ОТ SAMP.STAFF ГРУППА ПО ID - Получите столбцы AVGSALARY и EMPCOUNT, а также столбец DEPTNO, используя предложение AS. (.*) * \ (. * $ ',' \ 1 ') ||' ('|| qty ||') ',', ')
в группе
(упорядочить по item_id) res
из элемента;РЭС
-------------------------------------------------- -------------
Топленое масло суперем (23), гхи средний (12), Масло (47)
Oracle Training от Дона Бурлесона
Лучшее на сайте "Оракул Учебные курсы "находятся на расстоянии одного телефонного звонка! Вы можете пройти индивидуальное обучение Oracle от Дональда Бурлесона прямо в своем магазине!
Burleson - американская команда
Примечание: Этот оракул документация была создана как справочник по поддержке и обучению Oracle для использования нашими Специалисты-консультанты по настройке производительности администраторов баз данных. Не стесняйтесь задавать вопросы на нашем Форум Oracle.
Проверить опыт! Кто-нибудь рассматривая возможность использования услуг специалиста службы поддержки Oracle, следует самостоятельно исследовать их полномочия и опыт, а не полагаться на реклама и самопровозглашенная экспертиза. Все законные эксперты Oracle публиковать их оракул квалификации.
Опечатка? Технологии Oracle меняются, и мы стремимся обновлять нашу информацию о поддержке Oracle BC.Если вы обнаружите ошибку или у вас есть предложение по улучшению нашего содержания, мы будем признательны за ваше Обратная связь. Только Эл. адрес:
и укажите URL-адрес страницы.
Авторские права © 1996-2020
Все права защищены Бурлесон
Oracle
® является зарегистрированным товарным знаком Oracle Corporation.
Oracle SQL группирует по столбцу со счетчиком, но только если столбец имеет значение NULL или 0
Вкратце, я пытаюсь сгруппировать по столбцу, но только если этот столбец не
null
или0
, и в этом случае я все еще хочу получить эти строки, но только не сгруппированные.У меня есть эта таблицаsome_table
:+ -------- + ---------- + --------------------- + ----- - + | id | other_id | date_value | значение | + -------- + ---------- + --------------------- + ------- + | 1 | abc | 2011-04-20 21:03:05 | 104 | | 2 | abc | 2011-04-20 21:03:04 | 229 | | 3 | xyz | 2011-04-20 21:03:03 | 130 | | 4 | abc | 2011-04-20 21:02:09 | 97 | | 5 | 0 | 2011-04-20 21:02:08 | 65 | | 6 | xyz | 2011-04-20 21:02:07 | 101 | | 7 | | 2011-04-20 21:02:07 | 200 | | 8 | 0 | 2011-04-20 21:02:07 | 201 | | 9 | | 2011-04-20 21:02:07 | 202 | + -------- + ---------- + --------------------- + ------- +
Я хотел выбрать строки и сгруппировать по
other_id
, а также включить количество сгруппированных строк.Этот запрос работает:выберите id, other_id, date_value, value, cnt из ( ВЫБЕРИТЕ id, other_id, date_value, value, ROW_NUMBER () OVER (разделение по порядку other_id BY Date_Value desc) r, count (*) OVER (раздел по other_id) cnt ИЗ some_table ) где r = 1
Результат:
+ -------- + ---------- + --------------------- + ----- - + ------- + | id | other_id | date_value | значение | счет | + -------- + ---------- + --------------------- + ------- + ------- + | 1 | abc | 2011-04-20 21:03:05 | 104 | 3 | | 3 | xyz | 2011-04-20 21:03:03 | 130 | 2 | | 5 | 0 | 2011-04-20 21:02:08 | 65 | 2 | | 7 | | 2011-04-20 21:02:07 | 200 | 2 | + -------- + ---------- + --------------------- + ------- + ------- +
Проблема в том, что я не хочу группировать строки с
other_id
изnull
или0
.Итак, желаемый результат таков:+ -------- + ---------- + --------------------- + ----- - + ------- + | id | other_id | date_value | значение | счет | + -------- + ---------- + --------------------- + ------- + ------- + | 1 | abc | 2011-04-20 21:03:05 | 104 | 3 | | 3 | xyz | 2011-04-20 21:03:03 | 130 | 2 | | 5 | 0 | 2011-04-20 21:02:08 | 65 | 1 | | 7 | | 2011-04-20 21:02:07 | 200 | 1 | | 8 | 0 | 2011-04-20 21:02:07 | 201 | 1 | | 9 | | 2011-04-20 21:02:07 | 202 | 1 | + -------- + ---------- + --------------------- + ------- + ------- +
Как видите, все сгруппировано, за исключением случая, когда
other_id
равенnull
или0
, и в этом случае они все еще выбраны, но не сгруппированы.Еще пытаюсь заказать поdate_value
.Я попытался добавить предложение
WHERE
в предложениеOVER
:OVER (раздел по other_id, ГДЕ other_id НЕ НУЛЬ И other_id НЕ "0" порядок BY Date_Value desc) - это вызывает ошибку: ORA-00907: отсутствует правая скобка
Я подумал о том, чтобы выполнить второй запрос
select
и попытаться сложить первые результаты поверх второго, но я не думаю, что это сработает из-за упорядочивания.Есть ли способ такой группировки по условию?
4.6. Группирование и суммирование - Oracle SQL * Plus: Полное руководство, 2-е издание [Книга]
SQL позволяет разделить строки, возвращаемые запросом, на группы,
суммировать данные внутри каждой группы с помощью специального класса функций
известны как агрегатные функции и возвращают только одну строку для каждой группы. Например, вы можете
подсчитайте количество строк в таблице, используя функцию COUNT, показанную на
Пример 4-28.В Примере ничего нет
4-28, чтобы разделить извлекаемые данные на группы, чтобы все 11
строки в таблице сотрудников рассматриваются как одна группа. Функция СЧЁТ
- агрегатная функция, которая может подсчитывать количество значений или строк в
группа. COUNT особенный тем, что вы можете передать ему звездочку (*
), когда хотите подсчитать строки. Первое использование
of COUNT в примере показывает, что таблица содержит 11 строк. В
второе использование подсчитывает количество значений в
employee_termination_date
столбец.Нулевые значения не учитываются, поскольку нулевые значения представляют собой отсутствие значения.
Несмотря на то, что в деле зарегистрировано 11 сотрудников, в настоящее время работают только пятеро;
остальные шесть были уволены. Это вид бизнеса
информацию, которую вы можете получить, обобщив свои данные.Вы редко хотите суммировать данные по всей таблице.
Чаще вы будете разделять данные на группы. Для
Например, вы можете сгруппировать сотрудников по десятилетию, в котором они
были наняты, а затем задайте следующий вопрос: сколько сотрудников
из каждого десятилетия все еще работают? Пример 4-29 показывает, как это сделать.
это.Пример 4-29. Подсчет оставшихся сотрудников за каждое десятилетие
SELECT SUBSTR (TO_CHAR (employee_hire_date, 'YYYY'), 1,3) || '0' "декада",
COUNT (employee_hire_date) "нанят",
COUNT (employee_hire_date) - COUNT (employee_termination_date) "остальные",
MIN (employee_hire_date) «первый прием»,
MAX (employee_hire_date) "последний найм"
ОТ сотрудника
GROUP BY SUBSTR (TO_CHAR (employee_hire_date, 'YYYY'), 1,3) || '0';
Десятилетие наемный оставшийся первый наемный последний наемный ------------- ---------- ---------- ----------- ------ ----- 1960 3 1 15 ноября 1961 16 сентября 1964 1970 1 1 23 августа 1976 г. 23 августа 1976 г. 1980 1 0 29 декабря 1987 29 декабря 1987 1990 1 0 01 марта 1994 01 марта 1994 2000 5 3 02-янв-2004 15-июн-2004В дополнение к COUNT, в примере показаны функции MIN и MAX,
используется для возврата самой ранней и последней дат найма в каждой группе,
я.е., в пределах каждого десятилетия. Вы видите, что было нанято пять сотрудников
в 2000-х годах, когда все пять сотрудников были наняты в период с января по июнь.
2004. Двое из этих новых сотрудников с тех пор покинули компанию. Напротив,
у вас нет убыли людей, нанятых в 1980-х и 1990-х годах.
Возможно, вам следует выяснить, не
Департамент сбавляет темп найма!Стоит подробнее рассказать о том, как GROUP BY запрашивает
выполнять.Вы должны правильно понимать эти запросы. К
начало, на рис. 4-6 показано
всеслужащих
строк возвращены
предложением FROM.Рисунок 4-6. Операция FROM возвращает все строки сотрудников
Предложение GROUP BY затем разделяет сотрудников на группы по
десятилетие, как показано на рисунке
4-7. Функция TO_CHAR возвращает четырехзначный год каждого
дата найма сотрудника в виде символьной строки. Функция SUBSTR
извлекает с первой по третью цифры из этой строки, а
|| Оператор
используется для замены
четвертая цифра с нулем.Таким образом, все годы в диапазоне 1960-1969 гг.
трансформируется в строку «1960». (Приложение B содержит более подробную информацию
о применении TO_CHAR к датам.)Рисунок 4-7. Операция GROUP BY делит строки на группы
Группировка строк часто выполняется с помощью сортировки.
операция. Но как показано на рисунке
4-7 показано, что сортировка может быть неполной. Не рассчитывай на
GROUP BY, чтобы отсортировать вывод. Всегда используйте ORDER BY, если хотите результатов
в определенном порядке.После разделения строк на группы агрегатные функции
применяются, чтобы возвращать только одно значение для каждой группы. Рисунок 4-8 иллюстрирует это.
процесс только для одной группы строк, представляющих десятилетие
2000.Рисунок 4-8. Агрегатные функции применяются для возврата одной строки на
groupЕсть один столбец, возвращаемый оператором SELECT в примере 4-29, для которого
агрегатная функция не применялась. Этот столбец является вычисленным
столбец, который возвращает десятилетие, в которое был нанят сотрудник.Потому что
этот столбец является основой, по которой сотрудники делятся на группы,
имеет смысл вернуть его, чтобы вы знали, в какую группу каждый
применяется итоговая строка. Если вы опустите столбец «Десятилетие», результаты в
пример станет бесполезным. Хорошая идея - обозначить каждое резюме
строку, включив столбцы GROUP BY в результаты запроса.Предупреждение
Все столбцы, кроме перечисленных в предложении GROUP BY
к ним должна быть применена агрегатная функция.Вы не можете, потому что
Например, вернуть индивидуальные идентификаторы сотрудников из запроса, показанного в
Пример 4-29. Ты
должен применить агрегатную функцию для вычисления
только одно значение в столбце для каждой группы.В примере 4-29 используется
COUNT (employee_hire_date)
как
косвенный показатель количества сотрудников, нанятых за каждое десятилетие. Это
разумно, потому что пример дизайна базы данных исключает нули в
столбец даты найма. Однако все меняется, если нулевые даты найма
возможность.Если в данных должны были существовать нулевые даты найма, то эти
нули будут распространяться на протяжении всего десятилетия, и вы закончите
с единственной группой, у которой все нулевые даты найма. COUNT не будет
подсчитывать нулевые значения, поэтому применениеCOUNT (employee_hire_date)
к группе строк
со всеми нулевыми датами найма приведет к нулевому значению. Более того,
у вас могут быть даты увольнения в этой группе, поэтому результат
COUNT (дата_контроля_работника)
может быть больше нуля.Таким образом, среди всего остального результата вы
может закончиться странной строкой результатов, например:нанятых за десять лет, оставшихся первого нанятого, последнего найма ------------- ---------- ---------- --------- -------- - NULL 0-1 NULL NULLВ этом случае вам может быть лучше использовать
COUNT (*)
для подсчета строк, а не ненулевое значение
значения. Однако это устраняет симптом. Это может заставить математику выглядеть
лучше в результатах, но он ничего не делает для устранения лежащих в основе
проблема неверных данных.Настоящее решение - покопаться в ваших данных и найти
почему вы не записали даты приема на работу для некоторых из своих сотрудников.Возможно, вам не нужны все итоговые строки, возвращаемые GROUP BY
запрос. Вы знаете, что можно использовать WHERE для удаления строк с подробностями.
возвращается обычным запросом. С сводными запросами вы можете использовать
Предложение HAVING для исключения итоговых строк. Пример 4-30 показывает
Запрос GROUP BY, который использует HAVING для ограничения результатов только
те сотрудники, которые потратили более 20 часов на проекты 1001
и 1002.Пример 4-30. HAVING позволяет отфильтровать итоговые строки, которые вы не используете.
хочуВЫБЕРИТЕ employee_id, project_id
ОТ project_hours
ГРУППА ПО идентификатору сотрудника, идентификатору проекта
ИМЕЕТ (project_id = 1001 OR project_id = 1002)
AND SUM (hours_logged)> 20;
EMPLOYEE_ID PROJECT_ID ----------- ---------- 101 1002 107 1002 108 1002 111 1002Обратите внимание на использование
SUM (hours_logged)
для вычисления общего
количество часов, которые каждый сотрудник потратил на каждый проект.Этот
выражение появляется только в предложении HAVING, где оно используется для
ограничить вывод только этими комбинациями сотрудников / проектов
представляющие более 20 часов работы. Если хотите увидеть сумму,
вы также можете поместить выражение в предложение SELECT, но вы
не требуется этого делать.Пример 4-30 находится в
часть хороший пример того, как , а не использовать HAVING
пункт. HAVING выполняется после всей сортировки и суммирования GROUP
ПО.Любое условие, которое вы указываете в предложении HAVING, должно зависеть от
подведены итоги. Два условия в предложении HAVING примера 4-30 выполняют
не зависеть от сводных расчетов. Эти условия следует перенести
к предложению WHERE, как показано в Примере 4-31.Пример 4-31. Поместите несводные условия в предложение WHERE
SELECT employee_id, project_id
ОТ project_hours
ГДЕ project_id = 1001 OR project_id = 1002
ГРУППА ПО идентификатору сотрудника, идентификатору проекта
HAVING SUM (hours_logged)> 20;
EMPLOYEE_ID PROJECT_ID ----------- ---------- 101 1002 107 1002 108 1002 111 1002Причина, по которой вы помещаете все подробные условия в ГДЕ
предложение заключается в том, что предложение WHERE оценивается до группировки и
резюмируя работу GROUP BY.Чем меньше строк должно быть
отсортированы, сгруппированы и суммированы, чтобы повысить эффективность вашего запроса.
будет, и тем меньше будет нагрузка на сервер базы данных. Примеры Пример 4-30 и Пример 4-31 дают одинаковые
результаты, но пример
4-31 более эффективен, потому что он удаляет много строк раньше
в процессе выполнения запроса.ORA-00979: не группа по выражению
ORA-00979
ORA-00979 относится к предложению GROUP BY.Когда пользователь сталкивается с этой ошибкой, отображается следующее сообщение:
ORA-00979: не выражение GROUP BY
По сравнению с другими ошибками Oracle, ORA-00979 обычно проста и может быть легко решена одним из трех методов.
Проблема
ORA-00979 возникает, когда предложение GROUP BY не содержит всех выражений в предложении SELECT. Любое выражение SELECT, не включенное в функцию GROUP, должно быть указано в предложении GROUP BY.Это AVG, COUNT, MAX, MIN, SUM, STDDEV и VARIANCE. Возможно, вы также пытались выполнить оператор SELECT, содержащий предложение GROUP BY.
Решение
Чтобы исправить эту ошибку, включите все выражения SELECT в предложение GROUP BY. Убедитесь, что выражения не являются аргументами групповой функции. Есть три метода устранения этой ошибки.
- Перепишите инструкцию SELECT так, чтобы выражение или столбец, перечисленные в списке SELECT, также находились в предложении GROUP BY.
- Вы можете полностью удалить функцию GROUP BY из оператора SELECT.
- Удалите все выражения, не входящие в предложение GROUP BY, из списка SELECT.
Первый вариант исправления ошибки применим к следующему примеру, в котором пользователь пытается выполнить инструкцию SELECT:
ВЫБЕРИТЕ кафедру, класс, МАКС (количество) КАК «Наибольшее количество студентов»
ИЗ студентов
ГРУППОВОЙ отдел;
В этом примере ошибку можно исправить, включив class в предложение GROUP BY.Класс включен как в операторы SELECT, так и в GROUP BY.
ВЫБЕРИТЕ кафедру, класс, МАКС (количество) КАК «Наибольшее количество студентов»
ИЗ студентов
GROUP BY отдел, класс;
Взгляд в будущее
Чтобы не видеть ORA-00979, убедитесь, что выражения в списке SELECT также включены в предложение GROUP BY. Если выражение также находится в предложении GROUP BY, вы не должны увидеть ошибку.Если вы по-прежнему видите ошибку и не можете решить проблему, обратитесь к администратору базы данных. Вы также можете обратиться к лицензированному консультанту Oracle. Перед использованием их услуг всегда убедитесь, что у них есть надлежащие учетные данные, соответствующие уровню опыта, необходимому для удовлетворения ваших потребностей в Oracle.
нулевых значений в группе SQL по
Известно, что Null Null. Когда сравниваются два разных значения NULL, результатом является NULL (не TRUE), то есть два значения NULL не считаются равными.Применение того же правила к предложению GROUP BY заставит SQL помещать каждую строку с группирующим столбцом NULL в отдельную группу.
Но создание отдельной группы для каждой строки с NULL в столбце группирования сбивает с толку и бесполезно, поэтому разработчики написали стандарт SQL, в котором значения NULL считаются равными для целей предложения GROUP BY. Следовательно, если две строки имеют значения NULL в одних и тех же столбцах группировки и совпадают значения в оставшихся столбцах группировки, отличные от NULL, СУБД сгруппирует строки вместе.
Проще говоря, если столбец группировки содержит более одного значения NULL, значения NULL помещаются в одну группу.
Например, сгруппированный запрос:
SELECT A, B, SUM (amount_purchased) AS 'C'
FROM customers
GROUP BY A, B
ORDER BY A, Bотобразит таблицу результатов, аналогичную
A B C NULL NULL 61438.0000 NULL 101 196156.0000 AZ NULL 75815.0000 AZ 103 36958.0000 CA 101 78252.0000 6 LA NULL 00
9011 9011 9011 9011 9011 9011 9011 9011 9011 9016 для КЛИЕНТОВ, которые содержат следующие строки.
A B amount_purchased NULL NULL 45612.00000 NULL NULL 15826.00000 NULL 101 45852.0000 NULL 101 74815.0000 NULL 1019900 NULL 99116 NULL 75815.0000 AZ 103 36958.0000 CA 101 78252.0000 LA NULL 96385.0000 LA NULL 85247.0000 ВЫБРАТЬ (ГДЕ, ГРУППА ПО, ИМЕЮЩИЙ, ЗАКАЗАТЬ ПО) | Мой личный блог Oracle
TODO: поэкспериментируйте с другими примерами и ошибками
ВЫБРАТЬ
Выбрать все столбцы из таблицы
SELECT * FROM table_name;
ОТЛИЧИТЕЛЬНО
Выбор уникальных значений (неповторяющихся) из таблицы.Нет двух одинаковых имен.
ВЫБЕРИТЕ DISTINT имя_пользователя ИЗ имя_таблицы:
НИКНЕЙМЫ
Выберите определенные столбцы из таблицы и измените их имя на псевдоним
ВЫБЕРИТЕ столбец1, столбец2 как newNameOfColumn FROM table;
Использование функции для столбца в операторе SELECT
SELECT MAX (имя_столбца) FROM имя_таблицы;
ГДЕ
Используйте некоторые критерии для фильтрации строк, которые должны отображаться.
SELECT * FROM table_name WHERE column1 IS NOT NULL;
ВЫБРАТЬ * ИЗ имя_таблицы ГДЕ столбец1> = 10;
SELECT * FROM table_name WHERE column1 = 'некоторая строка, которая должна быть заключена в одинарные кавычки';
SELECT * FROM table_name WHERE column1 LIKE '_first character может быть любым, а затем он может заканчиваться 0 или неограниченным количеством любых символов%';
LIKE сопровождается двумя символами подстановки: символом процента (%) и символом подчеркивания (_).Символ процента используется для указания нуля или более символов подстановки, а символ подчеркивания указывает один символ подстановки.
ГРУППА ПО
Группировка столбцов по определенному критерию. Обратите внимание, что вы не можете использовать псевдонимы в GROUP BY и что вы должны иметь этот столбец в SELECT.
ВЫБРАТЬ столбец1 ИЗ имя_таблицы GROUP BY column1;
У вас должны быть все столбцы из SELECT в GROUP BY, иначе это не сработает. Следующие два утверждения приводят к ОШИБКЕ.
ВЫБРАТЬ * ИЗ имя_таблицы GROUP BY column1;
ВЫБРАТЬ столбец1, столбец2 ИЗ имя_таблицы GROUP BY column1;Если вы используете функцию для столбца 2, то она будет работать
ВЫБРАТЬ столбец1, СЧЁТ (столбец2) FROM имя_таблицы GROUP BY column1
Или, если мы поместим все столбцы из оператора SELECT в оператор GROUP BY.
ВЫБРАТЬ column1, column2 FROM table_name GROUP BY column1, column2
Если вы используете псевдоним для столбца, вы НЕ МОЖЕТЕ использовать его в операторе GROUP BY.Вы все еще можете использовать его в псевдониме WHERE
SELECT column1 AS. AVG (column2) как среднееColumn FROM table_name
GROUP BY column1;Следующий запрос приведет к ОШИБКЕ.
SELECT column1 AS псевдоним. AVG (столбец2) как средний столбец FROM имя_таблицы
псевдоним GROUP BY;ИМЕЕТ
HAVING фильтрует сгруппированные поля (в отличие от WHERE, который фильтрует все поля в таблице)
SELECT column1 FROM table_name WHERE column2 IS NOT NULL
GROUP BY column1 HAVING column1 = 'some value';Поскольку HAVING фильтрует только сгруппированные значения, столбец в HAVING также должен находиться в GROUP BY.Следующий запрос вернет ошибку.
ВЫБРАТЬ столбец 1 ИЗ имя_таблицы, ГДЕ столбец 2 НЕ ПУСТОЙ
ГРУППА ПО столбцу 1 ИМЕЕТ столбец 2 = 'какое-то значение';Этот запрос будет работать.
ВЫБРАТЬ столбец1, столбец2 ИЗ имя_таблицы, ГДЕ столбец2 НЕ ПУСТОЙ
ГРУППА ПО столбцу1, столбец2 ИМЕЕТ столбец2 = 'какое-то значение';Рассмотрим таблицу EMPLOYEES. Он состоит из 11 столбцов и 107 строк. Вы,
, можете создавать группы строк, которые имеют общее значение DEPARTMENT_ID.Затем можно использовать функцию
СУММ для создания итоговых зарплат по отделам.ВЫБРАТЬ макс (зарплата), количество (*) ИЗ сотрудников
ГРУППА ПО идентификатору отдела, имеющему count (*)> 1ЗАКАЗАТЬ ПО Department_id;
Любой элемент в списке SELECT, который не является групповой функцией, должен быть атрибутом группировки
предложения GROUP BY.Атрибут группировки обычно встречается в списке SELECT вместе с функциями группировки. Если элемент, который не является групповой функцией, появляется в списке SELECT и отсутствует предложение GROUP BY, возникает ошибка «ORA-00937: не групповая функция для одной группы».
SELECT end_date, COUNT (*) FROM job_history; ОШИБКА: ORA-00937: функция не одногрупповой группы
Если предложение GROUP BY присутствует, но этот элемент не является атрибутом группировки, то возвращается ошибка «ORA-00979: не выражение GROUP BY».
ВЫБРАТЬ end_date, start_date, COUNT (*) FROM job_history GROUP BY end_date; ОШИБКА: ORA-00979: не выражение GROUP BY
SELECT столбец | выражение | функция_группы (столбец | выражение [псевдоним]),…}
FROM table
[WHERE condition (s)]
[GROUP BY {col (s) | expr}]
[HAVING group_condition (s)]
[ORDER BY {col (s) | expr | numeric_pos} [ASC | DESC] [NULLS FIRST | LAST]];ЗАКАЗАТЬ В
ORDER BY просто определяет способ отображения результатов.Он сортирует результат на основе некоторого поля или нескольких полей, которые мы вводим, и может делать это по возрастанию ASC или убыванию DESC.
SELECT * | {[DISTINCT] столбец | выражение [псевдоним],…}
FROM table
[WHERE condition (s)]
[ORDER BY {col (s) | expr | numeric_pos} [ASC | DESC] [ ПЕРВЫЕ НУЛИ | ПОСЛЕДНИЙ ]];
ВЫБРАТЬ * ИЗ имя_таблицы ORDER BY column1 ASC;
ВЫБРАТЬ * ИЗ имя_таблицы ORDER BY column1 ASC, column2 DESC;При сортировке символов значения чувствительны к регистру.