단순한 중복 제거 기능 관점과의 차이점
그렇다 사실 그와는 달리에서 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
나는이 주제에 대해 블로그 포스트에서 더 깊이 글을 썼다