[sql] GROUP BY와 DISTINCT간에 차이점이 있습니까?

다른 날에 SQL에 대해 간단한 것을 배웠습니다.

SELECT c FROM myTbl GROUP BY C

다음과 같은 결과가 나타납니다.

SELECT DISTINCT C FROM myTbl

내가 궁금한 것은 SQL 엔진이 명령을 처리하는 방식에 다른 것이 있습니까? 아니면 실제로 같은 것입니까?

나는 개인적으로 뚜렷한 구문을 선호하지만 다른 것보다 습관이 더 확실하다고 확신합니다.

편집 : 이것은 집계에 대한 질문이 아닙니다. GROUP BY집계 함수와 함께 사용하는 것이 이해됩니다.



답변

MusiGenesis 의 응답은 명시된대로 귀하의 질문과 관련하여 기능적으로 올바른 것입니다. SQL Server는 “그룹화”를 사용하고 집계 함수를 사용하지 않는 경우 실제로 의미하는 것은 “고유”이므로 “Distinct”를 사용하는 것처럼 실행 계획을 생성한다는 사실을 충분히 잘 알고 있습니다. “

그러나 “Group By”와 “Distinct”에 대한 무심한 처리는 조심하지 않으면 일부 심각한 문제를 야기 할 수 있다는 Hank 의 반응 에 주목하는 것이 중요하다고 생각합니다 . 두 개의 SQL 쿼리 키워드 사이의 기능적 차이에 대해 질문하기 때문에 이것이 “집계에 대한 질문이 아니라”고 말하는 것은 전적으로 옳지 않습니다. 하나는 집계함께 사용되며 다른 하나는 그렇지 않습니다.

망치로 나사를 운전하는 경우도 있지만, 드라이버가 있으면 왜 귀찮습니까?

(이 비유의 목적 Hammer : Screwdriver :: GroupBy : Distinctscrew => get list of unique values in a table column)


답변

GROUP BY당신이 집계 함수를 사용할 수 있습니다 같은 AVG, MAX, MIN, SUM,와 COUNT. 반면에 DISTINCT중복을 제거합니다.

예를 들어 많은 구매 기록이 있고 각 부서에서 소비 한 금액을 알고 싶은 경우 다음과 같은 작업을 수행 할 수 있습니다.

SELECT department, SUM(amount) FROM purchases GROUP BY department

부서 이름과 amount해당 부서의 모든 행에있는 모든 값 의 합계를 포함하는 부서 당 하나의 행이 제공됩니다 .


답변

차이는 없습니다 (적어도 SQL Server에서는). 두 쿼리 모두 동일한 실행 계획을 사용합니다.

http://sqlmag.com/database-performance-tuning/distinct-vs-group

어쩌면이 있다 관여 서브 – 쿼리가있는 경우 차이는 :

http://blog.sqlauthority.com/2007/03/29/sql-server-difference-between-distinct-and-group-by-distinct-vs-group-by/

차이점은 없습니다 (Oracle 스타일).

http://asktom.oracle.com/pls/asktom/f?p=100:11:0:::::P11_QUESTION_ID:32961403234212


답변

단순한 중복 제거 기능 관점과의 차이점

그렇다 사실 그와는 달리에서 DISTINCT, GROUP BY데이터 집계를 허용 그룹당를 (다른 많은 답변 언급 된), 제 생각에 가장 중요한 차이점은 두 작업은 두 개의 매우 다른 단계에서 “일”사실이다 논리적 인 순서는 SELECT명령문 에서 실행되는 조작의 수 .

가장 중요한 작업은 다음과 같습니다.

  • FROM(비롯한 JOIN, APPLY등)
  • WHERE
  • GROUP BY (중복 제거 가능)
  • 집계
  • HAVING
  • 창 기능
  • SELECT
  • DISTINCT (중복 제거 가능)
  • UNION, INTERSECT, EXCEPT (중복을 제거 할 수 있습니다)
  • ORDER BY
  • OFFSET
  • LIMIT

보다시피, 각 작업의 논리적 순서는 수행 할 수있는 작업과 후속 작업에 미치는 영향에 영향을줍니다. 특히, 실제로는 것을 GROUP BY동작 “하기 전에 일어나는”SELECT 동작 (돌기) 의미 :

  1. 그것은 투영에 의존하지 않습니다 (이점이 될 수 있습니다)
  2. 프로젝션의 값을 사용할 수 없습니다 (불이익이 될 수 있음)

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

나는이 주제에 대해 블로그 포스트에서 더 깊이 글을 썼다


답변

DISTINCT중복을 제거하려는 경우에 사용하십시오 . 사용 GROUPY BY이 집계 연산자를 적용 할 경우 ( MAX, SUM, GROUP_CONCAT, …, 또는 HAVING절).


답변

나는 그들의 실행에 미묘한 차이가있을 가능성이 있다고 생각합니다. Oracle 10g에서 다음 라인을 따라 기능적으로 동등한 두 쿼리에 대한 실행 계획을 확인했습니다.

core> select sta from zip group by sta;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH GROUP BY     |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

core> select distinct sta from zip;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH UNIQUE       |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

중간 작업은 “HASH GROUP BY”와 “HASH UNIQUE”가 약간 다르지만 예상 비용 등은 동일합니다. 그런 다음 추적 기능을 사용하여이를 실행했으며 실제 작업 수는 두 항목 모두 동일했습니다 (두 번째 캐시는 캐싱으로 인해 실제 읽기를 수행하지 않아도 됨).

그러나 작업 이름이 다르기 때문에 실행이 약간 다른 코드 경로를 따르고 더 큰 차이가 발생할 가능성이 있다고 생각합니다.

이 목적으로 DISTINCT 구문을 선호해야한다고 생각합니다. 그것은 습관이 아니라 쿼리의 목적을 더 명확하게 나타냅니다.


답변

게시 한 쿼리의 경우 동일합니다. 그러나 다른 쿼리의 경우에는 그렇지 않을 수 있습니다.

예를 들어, 다음과 동일하지 않습니다.

SELECT C FROM myTbl GROUP BY C, D