문제

내가 뭔가를 배웠는 간단에 대한 SQL 다른 일:

SELECT c FROM myTbl GROUP BY C

결과는 같습니다:

SELECT DISTINCT C FROM myTbl

나의 궁금,아무거나 다른 방식에서는 SQL 엔진 프로세스의 명령 또는 그들이 진정으로 같은 것은?

나 개인적으로 선호하는 뚜렷한 구문,하지만 난 그것은 더 많은 습관이 무엇보다.

편집:이 질문에 대해 집계가 있습니다.의 사용 GROUP BY 으로 집계 기능을 파악해야 합니다.

도움이 되었습니까?

해결책

musigenesis'응답은 언급 된대로 귀하의 질문과 관련하여 기능적으로 올바른 것입니다. SQL Server는 "Group By"를 사용하고 집계 함수를 사용하지 않는 경우 실제로 의미하는 바는 "별개"라는 것을 깨닫기에 충분히 똑똑합니다. 따라서 간단하게 사용한 것처럼 실행 계획을 생성합니다. . "

그러나 나는 주목하는 것이 중요하다고 생각합니다 다발"Group By"및 "Contrest"에 대한 무심한 대우는 조심하지 않으면 일부 악한 gotchas로 이어질 수 있습니다. 두 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 서버에서). 두 쿼리 모두 동일한 실행 계획을 사용합니다.

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

어쩌면 거기 ~이다 하위 쿼리가 관련된 경우 차이 :

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

다른 점이 없다 (오라클 스타일) :

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

사용 DISTINCT 중복을 제거하려는 경우. 사용 GROUPY BY 집계 연산자를 신청하려면 (MAX, SUM, GROUP_CONCAT, ... 또는 a HAVING 절).

단순한 중복 제거 기능 관점과의 차이점은 무엇입니까?

사실과는 달리 DISTINCT, GROUP BY 집계 데이터가 허용됩니다 그룹당 (다른 많은 답변에 의해 언급 된), 내 의견에서 가장 중요한 차이점은 두 가지 작전이 다음과 같은 두 단계에서 "발생한다"는 사실입니다. a에서 실행되는 논리적 운영 순서 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

에 대항 할 때 사칠라 데이터베이스, 이것은 수율 :

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

블로그 게시물 에서이 주제에 대해 더 깊이 글을 썼습니다.

제가 기대 가능성이 있는 미묘한 차이점들의 실행에 있습니다.체크에 대한 실행 계획은 두 개의 기능적으로 동등한 쿼리를 따라 이러한 라인에서 Oracle10g:

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 |
---------------------------------------------------------------------------

중간 작업은 약간 다르다:"해쉬 그룹에 의해"대."해시한"하지만,예상 비용 등입니다.은 동일합니다.나는 그때 실행으로 이러한 추적을 설정하고 실제 동작 카운트에게 동일한 모두(제외하고는 두 번째 중 하나 있지 않은지 어떤 물리적 읽기 때문에 캐싱).

그러나 내가 생각하기 때문에 그 작업이 이름이 다른 실행을 따라 다소 다른 코드로와 그의 가능성을 열어 더 중요한 차이점이 있습니다.

생각해야 합아보세요한 구문을 이 목적을 위해.그것은 단지 습관은,그것을 좀 더 명확하게 나타내의 목적은 쿼리가 있습니다.

게시 한 쿼리의 경우 동일합니다. 그러나 다른 쿼리의 경우 사실이 아닐 수도 있습니다.

예를 들어, 그것은 다음과 같지 않습니다.

SELECT C FROM myTbl GROUP BY C, D

위의 모든 의견을 읽었지만 집계 비트와는 별도로 그룹과 뚜렷한 그룹의 주요 차이점을 지적하지 않았습니다.

별개의 모든 행을 반환 한 다음 해제를 제거하는 반면, 그룹은 알고리즘에 의해 읽은 것처럼 행을 제거하여 그룹을 하나씩 사용합니다.

이것은 그들이 다른 결과를 생성 할 수 있음을 의미합니다!

예를 들어 아래 코드는 다른 결과를 생성합니다.

SELECT distinct ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable

 SELECT ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable
GROUP BY Name

테이블에 10 개의 이름이있는 경우 1 개의 이름이 다른 하나의 복제본 인 경우 첫 번째 쿼리는 10 행을 반환하는 반면 두 번째 쿼리는 9 행을 반환합니다.

그 이유는 내가 위에서 말한 것 때문에 그들이 다르게 행동 할 수 있기 때문입니다!

여러 열에서 별개의 사용을 사용하는 경우 결과 세트는 Group By와 같이 그룹화되지 않으며 고유 한 집계 기능을 사용할 수 없습니다.

특정 데이터에 동등한 결과를 얻더라도 의미론이 다릅니다.

그룹은 별개의 기능과 구별되는 매우 구체적인 의미를 갖습니다.

그룹별로 쿼리 결과가 선택된 표현식을 사용하여 그룹화되도록 원인으로, 집계 함수를 적용 할 수 있으며, 이들은 전체 결과가 아닌 각 그룹에 작용합니다.

다음은 도움이 될 수있는 예입니다.

다음과 같이 보이는 테이블이 주어졌습니다.

name
------
barry
dave
bill
dave
dave
barry
john

이 쿼리 :

SELECT name, count(*) AS count FROM table GROUP BY name;

다음과 같은 출력을 생성합니다.

name    count
-------------
barry   2
dave    3
bill    1
john    1

그것은 별개의 사용과 분명히 매우 다릅니다. 결과를 그룹화하려면 그룹을 사용하십시오. 특정 열의 고유 한 목록을 원한다면 별개의 사용을 사용하십시오. 이렇게하면 데이터베이스에 요구 사항에 대한 쿼리를 최적화 할 수있는 기회가 제공됩니다.

당신이 뚜렷한 것을 의미 할 때까지 그룹을 사용하지 마십시오. 나는 당신이 쿼리에서 밀리 초를 면도하려고한다고 가정하고 있으며, 개발자 시간은 컴퓨터 시간보다 더 비싸다는 것을 지적해야합니다.

집계 기능없이 그룹을 사용하는 경우 내부적으로는 뚜렷한 것으로 취급 되므로이 경우 그룹에 의한 그룹과 별개 사이에는 차이가 없습니다.

그러나 그룹의 목표는 집계를 달성하는 것이기 때문에 고유 한 레코드를 찾는 데 사용하는 것이 더 나은 조항을 제공받을 때.

Group By는 집계 작업에 사용됩니다. C 열 C로 BS를 세고 싶을 때와 같이.

select C, count(B) from myTbl group by C

뚜렷한 소리는 소리입니다. 독특한 행을 얻습니다.

SQL Server 2005에서 쿼리 옵티마이저가 내가 실행 한 단순한 예제의 차이를 최적화 할 수있는 것처럼 보입니다. 그래도 모든 상황에서이를 믿을 수 있다면 Dunno.

그 특정 쿼리에는 차이가 없습니다. 그러나 물론 집계 열을 추가하면 그룹을 사용해야합니다.

'SQL'언어 '관점에서 두 가지 구성은 동일하며 선택한 구성은 우리 모두가해야 할'라이프 스타일 '선택 중 하나입니다. 나는 더 명확하게 표현할 수있는 좋은 사례가 있다고 생각합니다 (따라서 코드 등을 상속받을 사람에게 더 배려 할 것입니다). 그러나 Construct의 그룹이 잘못된 선택이라는 의미는 아닙니다.

나는이 '그룹에 의한 그룹이 집계를위한 그룹'이 잘못된 강조라고 생각합니다. 사람들은 코더의 의도를 이해할 수 있도록 설정 함수 (Max, Min, Count 등)를 생략 할 수 있음을 알고 있어야합니다.

이상적인 최적화기는 동등한 SQL 구성을 인식하고 항상 이상적인 계획을 선택합니다. 선택한 실제 SQL 엔진을 위해 테스트해야합니다. :)

추신 : 선택 절에서 고유 한 키워드의 위치는 다른 결과를 생성 할 수 있습니다.

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

에 관점 Teradata :

에서 그 결과로 설정한 관점,그것은 중요하지 않습니다 당신이 사용하는 경우 또는 뚜렷한 그룹에 의해서 Teradata.응답을 설정이 동일합니다.

에서 성능의 관점,그것은 동일하지 않습니다.

을 이해하는 것이 성능에 미치는,당신이 무엇을 알아야에서 일어나는 Teradata 문을 실행하는 경우 또는 뚜렷한 그룹이다.

의 경우에는 뚜렷한,행을 재배포할 수 있지 않고 바로 어떤 preaggregation 복용하는 경우에는 그룹으로,첫 번째 단계에서는 preaggregation 수행하고 다음에는 고유한 값을 재배포에서 암페어입니다.

고 생각하지 않는 것이 지금 그룹에 의해 항상에서 더 나은 성능의 관점입니다.면 당신은 많은 서로 다른 값을 preaggregation 단계의 그룹에 의해은 매우 효율적이지 않습니다.Teradata 는 데이터를 정렬하고 중복을 제거하십시오.이 경우에는 것이 더 나을 수도 있습니다 재배포 첫째,즉를 사용하여 별개의 문입니다.만 많은 경우에는 값이 중복되 그룹에 의해 진술은 아마도 더 나은 선택으로만하면 단계 중복 제거 장소,후 재배포.

에 뚜렷한 대그룹에 의해서 Teradata 의미합니다:

그룹에 의해->를 위한 많은 중복 DISTINCT->없는 몇 가지 중복니다.시간을 사용할 때 뚜렷한,당신은 당신의 스풀에 있는 공간입니다.그 이유는 재배포는 즉시,그리고 왜곡 발생할 수 있습 AMPs 을 실행하는 공간이 부족합니다.

이 경우,당신은 아마 더 나은 기회를 가진 그룹에 의해,중복으로 이미 제거 첫 번째 단계에서,그리고 데이터의 맞은편에 이동됩니다 AMPs.

단일 열을 선택하고 있기 때문에 그 사실 만 알고 있습니다.

두 필드를 선택하고 어떤 일이 일어나는지 확인하십시오.

Group By는 다음과 같이 사용하도록 의도됩니다.

SELECT name, SUM(transaction) FROM myTbl GROUP BY name

각 사람에 대한 모든 거래의 합이 표시됩니다.

나는 그것이 오래된 게시물이라는 것을 알고 있습니다. 그러나 Toad에서 해당 쿼리를 사용할 때 뚜렷한 값을 반환하기 위해 그룹을 사용한 쿼리가 있었으며 Oracle 보고서는 모든 것이 잘 작동했습니다. 응답 시간이 좋은 것을 의미합니다. 우리가 Oracle 9i에서 11g으로 마이그레이션했을 때 두꺼비의 응답 시간은 우수했지만 보고서에서는 이전 버전을 사용할 때 보고서를 완료하는 데 약 35 분이 걸렸습니다. 약 5 분이 걸렸습니다.

해결책은 그룹을 변경하고 뚜렷하게 사용하는 것이 었으며 이제 보고서는 약 30 초 안에 실행됩니다.

나는 이것이 같은 상황을 가진 사람에게 유용하기를 바랍니다.

내가 항상 이해하는 방식은 구별을 사용하는 것이 선택한 순서대로 선택한 모든 필드별로 그룹화하는 것과 동일하다는 것입니다.

즉:

select distinct a, b, c from table;

와 같다:

select a, b, c from table group by a, b, c

기능 효율성은 완전히 다릅니다. 중복 값을 제외하고 "반환 값"만 선택하려면 그룹보다 별개가 더 좋습니다. "그룹"include (정렬 + 제거), "별개"포함 (제거).

Hive (HQL)에서, 그룹은 뚜렷한 것보다 빠를 수 있습니다. 전자는 테이블의 모든 필드를 비교할 필요가 없기 때문입니다. 보다 https://sqlperformance.com/2017/01/t-sql-queries/surprises-assumptions-group-by-distinct.

집계 함수의 사용을 제외하고 그룹에 의한 그룹과 별개의 절 사이에는 유의 한 차이가 없습니다. 둘 다 값을 구별하는 데 사용될 수 있지만 성능 관점에서 그룹에 의해 더 좋습니다. 별개의 키워드가 사용되면 내부적으로 실행 계획에서 볼 수있는 정렬 작업을 사용했습니다.

간단한 예제를 시도하십시오

@tmpresult 테이블 선언 (ID tinyint)

@tmpresult에 삽입 5 Union All Select 2 Union All Select 3 Union All Select 4

@tmpresult에서 고유 한 ID를 선택하십시오

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top