У чому полягає відмінність від простого дублювання функцій видалення з точки зору
Крім того, що на відміну від того DISTINCT, що GROUP BYдозволяє агрегувати дані по групі (про що згадувалося в багатьох інших відповідях), найважливішою відмінністю, на мою думку, є той факт, що дві операції "відбуваються" на двох дуже різних кроках у логічному порядку операцій, які виконуються у SELECTвиписці .
Ось найважливіші операції:
FROM( В тому числі JOIN, APPLYі т.д.)
WHERE
GROUP BY (може видалити дублікати)
- Агрегації
HAVING
- Віконні функції
SELECT
DISTINCT (може видалити дублікати)
UNION, INTERSECT, EXCEPT (Можна видалити дублікати)
ORDER BY
OFFSET
LIMIT
Як бачимо, логічний порядок кожної операції впливає на те, що можна зробити з нею і як вона впливає на наступні операції. Зокрема, той факт , що GROUP BYоперація «відбувається до» на SELECTоперації (проекція) означає , що:
- Це не залежить від проекції (що може бути перевагою)
- Він не може використовувати жодні значення проекції (що може бути недоліком)
1. Це не залежить від проекції
Приклад, коли не залежно від проекції є корисним, якщо ви хочете обчислити віконні функції за різними значеннями:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating
Якщо працювати з базою даних Sakila , це дає:
rating rn
-----------
G 1
NC-17 2
PG 3
PG-13 4
R 5
Те ж неможливо досягти DISTINCTлегко:
SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
Цей запит є "неправильним" і дає щось на кшталт:
rating rn
------------
G 1
G 2
G 3
...
G 178
NC-17 179
NC-17 180
...
Це не те, чого ми хотіли. DISTINCTОперація «не відбувається після того, як " проекція, тому ми більше не можемо видалити DISTINCTрейтинги , тому що функція вікна вже розраховані і прогнозовані. Для використання DISTINCTнам слід вкласти ту частину запиту:
SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
SELECT DISTINCT rating FROM film
) f
Побічна примітка: У цьому конкретному випадку ми могли б також використатиDENSE_RANK()
SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film
2. Він не може використовувати жодні значення проекції
Одним з недоліків SQL є його багатослівність часом. З тієї ж причини, що ми бачили раніше (а саме логічний порядок операцій), ми не можемо «легко» згрупувати те, що ми проектуємо.
Це недійсний SQL:
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name
Це дійсно (повторення виразу)
SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name
Це також справедливо (вкладення виразу)
SELECT name
FROM (
SELECT first_name || ' ' || last_name AS name
FROM customer
) c
GROUP BY name
Я писав про цю тему більш глибоко в публікації в блозі