다른 날에 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 : Distinct
및 screw => 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
어쩌면이 있다 관여 서브 – 쿼리가있는 경우 차이는 :
차이점은 없습니다 (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. 그것은 투영에 의존하지 않습니다
투영에 의존하지 않는 유용한 예는 별개의 값으로 창 기능을 계산하려는 경우입니다.
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
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