GROUP BY без агрегатной функции
Я пытаюсь понять GROUP BY (новый для оракула dbms) без агрегатной функции.
Как это работает?
Вот что я пробовал.
Таблица EMP, на которой я буду запускать свой SQL.
SELECT ename , sal
FROM emp
GROUP BY ename , sal
SELECT ename , sal
FROM emp
GROUP BY ename;
Результат
ORA-00979: не выражение GROUP BY
00979. 00000 - "не выражение GROUP BY"
* Причина:
* Действие:
Ошибка в строке: 397 Колонка: 16
SELECT ename , sal
FROM emp
GROUP BY sal;
Результат
ORA-00979: не выражение GROUP BY
00979. 00000 - "не выражение GROUP BY"
* Причина:
* Действие: Ошибка в строке: 411 Колонка: 8
SELECT empno , ename , sal
FROM emp
GROUP BY sal , ename;
Результат
ORA-00979: не выражение GROUP BY
00979. 00000 - "не выражение GROUP BY"
* Причина:
* Действие: Ошибка в строке: 425 Колонка: 8
SELECT empno , ename , sal
FROM emp
GROUP BY empno , ename , sal;
Итак, в основном число столбцов должно быть равно числу столбцов в предложении GROUP BY, но я до сих пор не понимаю, почему и что происходит.
Ответы
Ответ 1
Как работает GROUP BY. Он занимает несколько строк и превращает их в одну строку. Из-за этого он должен знать, что делать со всеми объединенными строками, где для некоторых столбцов (полей) есть разные значения. Вот почему у вас есть два варианта для каждого поля, которое вы хотите выбрать: либо включить его в предложение GROUP BY, либо использовать его в агрегатной функции, чтобы система знала, как вы хотите объединить это поле.
Например, скажем, у вас есть эта таблица:
Name | OrderNumber
------------------
John | 1
John | 2
Если вы скажете "GROUP BY Name", как он узнает, какой номер OrderNumber будет показан в результате? Таким образом, вы либо включаете OrderNumber в группу, что приведет к этим двум строкам. Или вы используете агрегированную функцию, чтобы показать, как обрабатывать OrderNumbers. Например, MAX(OrderNumber)
, что означает результат John | 2
или SUM(OrderNumber)
, что означает, что результат John | 3
.
Ответ 2
Вы испытываете строгое требование предложения GROUP BY. Каждый столбец, не содержащийся в предложении group-by, должен иметь функцию, применяемую для уменьшения всех записей для соответствующей "группы" до одной записи (сумма, макс, мин и т.д.).
Если вы укажете все столбцы запроса (выбранные) в предложении GROUP BY, вы по существу запрашиваете, чтобы дублирующие записи были исключены из набора результатов. Это дает тот же эффект, что и SELECT DISTINCT, который также исключает повторяющиеся строки из набора результатов.
Ответ 3
Учитывая эти данные:
Col1 Col2 Col3
A X 1
A Y 2
A Y 3
B X 0
B Y 3
B Z 1
Этот запрос
SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2, Col3
Результатом будет та же таблица.
Однако этот запрос:
SELECT Col1, Col2 FROM data GROUP BY Col1, Col2
Результат
Col1 Col2
A X
A Y
B X
B Y
B Z
Теперь запрос:
SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2
Создаст проблему: строка с A, Y является результатом группировки двух строк
A Y 2
A Y 3
Итак, какое значение должно быть в Col3, '2' или '3'?
Обычно вы должны использовать группу для вычисления, например. сумма:
SELECT Col1, Col2, SUM(Col3) FROM data GROUP BY Col1, Col2
Итак, в строке мы столкнулись с проблемой: теперь мы получаем (2 + 3) = 5.
Группировка всеми вашими столбцами в вашем элементе фактически аналогична использованию DISTINCT, и в этом случае предпочтительно использовать читабельность слова ключевого слова DISTINCT.
Итак, вместо
SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2
использование
SELECT DINSTINCT Col1, Col2, Col3 FROM data
Ответ 4
Единственный реальный случай использования GROUP BY без агрегации - это когда вы GROUP BY больше столбцов, чем выбрано, и в этом случае выбранные столбцы могут быть повторены. В противном случае вы можете использовать DISTINCT.
Стоит отметить, что в других СУБД не требуется включать все неагрегированные столбцы в GROUP BY. Например, в PostgreSQL, если столбцы первичного ключа в таблице включены в GROUP BY, тогда другие столбцы этой таблицы не должны быть такими, какими они гарантированы для каждого отдельного столбца первичного ключа. В прошлом я хотел, чтобы Oracle делала то же самое, что и во многих случаях для более компактного SQL.
Ответ 5
Позвольте мне привести несколько примеров.
Рассмотрим эти данные.
CREATE TABLE DATASET ( VAL1 CHAR ( 1 CHAR ),
VAL2 VARCHAR2 ( 10 CHAR ),
VAL3 NUMBER );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'b', 'b-details', 2 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'a', 'a-details', 1 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'c', 'c-details', 3 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'a', 'dup', 4 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'c', 'c-details', 5 );
COMMIT;
Что там в таблице сейчас
SELECT * FROM DATASET;
VAL1 VAL2 VAL3
---- ---------- ----------
b b-details 2
a a-details 1
c c-details 3
a dup 4
c c-details 5
5 rows selected.
- совокупность с группой
SELECT
VAL1,
COUNT ( * )
FROM
DATASET A
GROUP BY
VAL1;
VAL1 COUNT(*)
---- ----------
b 1
a 2
c 2
3 rows selected.
- совокупность с группой по нескольким столбцам, но выберите частичный столбец
SELECT
VAL1,
COUNT ( * )
FROM
DATASET A
GROUP BY
VAL1,
VAL2;
VAL1
----
b
c
a
a
4 rows selected.
- нет агрегата с группой по нескольким столбцам
SELECT
VAL1,
VAL2
FROM
DATASET A
GROUP BY
VAL1,
VAL2;
VAL1
----
b b-details
c c-details
a dup
a a-details
4 rows selected.
- нет агрегата с группой по нескольким столбцам
SELECT
VAL1
FROM
DATASET A
GROUP BY
VAL1,
VAL2;
VAL1
----
b
c
a
a
4 rows selected.
У вас есть N столбцов в select (исключая агрегации), тогда вы должны иметь столбцы N или N + x
Ответ 6
Если у вас есть столбец в предложении SELECT, как он будет выбирать его, если есть несколько строк? поэтому да, каждый столбец в предложении SELECT также должен быть в условии GROUP BY, вы можете использовать агрегатные функции в SELECT...
у вас может быть столбец в предложении GROUP BY, который не находится в предложении SELECT, но не иначе
Ответ 7
Использовать вспомогательный запрос, например:
SELECT field1,field2,(SELECT distinct field3 FROM tbl2 WHERE criteria) AS field3
FROM tbl1 GROUP BY field1,field2
ИЛИ
SELECT DISTINCT field1,field2,(SELECT distinct field3 FROM tbl2 WHERE criteria) AS field3
FROM tbl1
Ответ 8
Я знаю, что вы сказали, что хотите понять группу, если у вас есть такие данные:
COL-A COL-B COL-C COL-D
1 Ac C1 D1
2 Bd C2 D2
3 Ba C1 D3
4 Ab C1 D4
5 C C2 D5
И вы хотите, чтобы данные выглядели следующим образом:
COL-A COL-B COL-C COL-D
4 Ab C1 D4
1 Ac C1 D1
3 Ba C1 D3
2 Bd C2 D2
5 C C2 D5
Вы используете:
select * from table_name
order by col-c,colb
Потому что я думаю, что это то, что вы намереваетесь сделать.
Ответ 9
В качестве дополнения
в основном число столбцов должно быть равно числу столбцов в предложении GROUP BY
не является правильным утверждением.
- Любой атрибут, который не является частью предложения GROUP BY, не может использоваться для выбора
- Любой атрибут, являющийся частью предложения GROUP BY, может использоваться для выбора, но не обязательно.