2010-03-08 8 views
233

나는 지난 수년 동안 모든 유형의 집계 쿼리에 GROUP BY을 사용 해왔다. 최근에 나는 PARTITION BY을 사용하여 집계를 수행하는 일부 코드를 리버스 엔지니어링했습니다. 내가 대략 PARTITION BY에 대해 찾을 수있는 모든 문서를 읽으면서, 아마도 약간의 추가 기능이 추가 된 GROUP BY과 비슷하게 들릴 것입니까? 동일한 일반 기능의 두 가지 버전입니까, 아니면 완전히 다른 것입니까?SQL Server : PARTITION BY와 GROUP BY의 차이점

답변

270

그들은 다른 장소에서 사용됩니다.

select customerId, count(*) as orderCount 
from Orders 
group by customerId 

그러나 partition by 단지 row_number처럼, a window function에서 작동 : group by처럼, 전체 쿼리를 수정

select row_number() over (partition by customerId order by orderId) 
    as OrderNumberForThisCustomer 
from Orders 

일반적으로 평균 또는 합계를 그들을 압연 계산하여 반환되는 행의 수를 감소 group by 각 행에 대해 partition by은 반환 된 행의 수에는 영향을 미치지 않지만 창 함수의 결과가 계산되는 방식은 변경됩니다.

+8

멋진 답변, 각각에 대해 반환 된 결과의 샘플을 작성 하시겠습니까? –

+2

@AshkanMobayenKhiabani Northwind에 대해 두 가지 쿼리를 실행할 수 있습니다.이 쿼리는 SQL Server 버전에 따라 기본적으로 설치되거나 설치되지 않을 수 있습니다. 그렇지 않다면 s 다운로드 페이지에서 검색 할 수 있습니다. –

+9

@AshkanMobayenKhiabani Arunprasanth의 답변은 더 많은 학습 농구와 Northwind를 배울 시간을 뛰어 넘는 것과 반대로 시간을 절약 할 수있는 결과를 보여줍니다. – Praxiteles

42

partition by 실제로 데이터를 롤업하지 않습니다. 그룹 단위로 무언가를 재설정 할 수 있습니다. 예를 들어 그룹화 필드를 분할하고 해당 그룹 내의 행에 rownum()을 사용하여 그룹 내의 서수 열을 가져올 수 있습니다. 이렇게하면 각 그룹의 시작 부분에서 재설정되는 ID 열과 같이 약간 동작하는 것을 얻을 수 있습니다.

20

은 분석적이며, GROUP BY은 집합입니다. PARTITION BY을 사용하려면 OVER clause으로 입력해야합니다.

+0

'PARTITION BY는 분석적입니다. '이 간단한 문장은 제게 많은 도움을줍니다. +1. –

33

분할 영역 결과 집합을 분할하여 분할합니다. 창 함수는 각 파티션에 개별적으로 적용되며 각 파티션에 대한 계산이 다시 시작됩니다. 이 링크에서 찾을 수

: OVER Clause

22

그것은 즉

을 압연 내가 파티션 BY를 사용하여 판매 지역

의 상대 위치를 반환한다고 가정하지 않고 겹쳐서 데이터를 제공, I 주어진 지역의 판매 금액을 동일한 행에있는 모든 판매 지역의 최대 금액 인 을 반환 할 수 있습니다.

이것은 데이터 반복을 의미하지만 GROUP BY의 경우처럼 데이터가 집계되었지만 손실 된 데이터가 없음을 의미하는 최종 소비자에게 적합 할 수 있습니다. 으로 나의 이해 파티션의로

+0

가장 간단하고 간단한 답변입니다. – tmthyjames

18

그룹으로 거의 동일하지만 다음과 같은 차이점 :

그 결과는에서만 허용 SQL 서버에 따라서 결과 그룹 당 하나 개의 행을 반환 설정 실제로 단체 그룹 SELECT by group by 절의 일부인 집계 함수 또는 열 (SQL Server는 각 그룹에 고유 한 결과가 있음을 보장 할 수 있음).

예를 들어 Group By 절에 정의되지 않은 SELECT 목록의 열을 가질 수있는 MySQL을 고려해보십시오.이 경우 그룹 당 하나의 행이 여전히 반환되지만 열에 고유 한 결과가없는 경우 출력이 무엇인지 보장 할 수는 없습니다!

그러나 Partition By를 사용하면 함수 결과가 Group By 집계 함수의 결과와 동일하지만 여전히 기본 결과 집합을 얻게됩니다. 즉, 기본 행당 하나의 행을 가져 오는 것을 의미합니다. 그룹당 하나의 행이 아니므로 SELECT 목록의 그룹별로 고유하지 않은 열을 가질 수 있습니다.

요약하면 Group By는 그룹 당 한 행의 출력이 필요할 때 가장 좋으며 Partition By는 모든 행이 필요하지만 그룹을 기반으로하는 집계 함수를 원할 때 가장 좋을 것입니다.

물론 성능 문제가있을 수도 있습니다 (http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba 참조).

127

우리는 우리가 다음과 같은 값으로 TableA라는 이름의 테이블이 간단한 예

수 있습니다.

id firstname     lastname     Mark 
------------------------------------------------------------------- 
1 arun      prasanth     40 
2 ann       antony      45 
3 sruthy      abc       41 
6 new       abc       47 
1 arun      prasanth     45 
1 arun      prasanth     49 
2 ann       antony      49 

그룹

하여 SQL group by 절은 여러 레코드 및 그룹 하나 이상의 열을 기준으로 결과를 통해 데이터를 수집하기 위해 SELECT 문에서 사용할 수 있습니다.

보다 간단한 용어로 GROUP BY 문은 과 함께 사용되어 하나 이상의 열로 결과 집합을 그룹화하는 집계 함수를 사용합니다.

구문 :

SELECT expression1, expression2, ... expression_n, 
     aggregate_function (aggregate_expression) 
FROM tables 
WHERE conditions 
GROUP BY expression1, expression2, ... expression_n; 

우리는

select SUM(Mark)marksum,firstname from TableA 
group by id,firstName 

결과 우리 테이블에서 GROUPBY을 적용 할 수 있습니다 : 우리는 7 개 행이 우리의 실제 테이블에서

marksum firstname 
---------------- 
94  ann      
134  arun      
47  new      
41  sruthy 

을 때 우리는 이드에 의해 그룹을 적용한다. 서버 그룹 일반적으로 간단한 여기 단어

기 이드

에 기초하여 결과들을 을 압 및 행마다 합계를 계산하여 반환 된 행의 수는 줄일 수있다.

파티션

에 의해

에 의해 분할 전에 절 OVER

이 창을 정의 우리가 OVER 절 MSDN의 정의에 따라

살펴 보자 또는 사용자 지정 행 세트 wi thin 결과는 입니다. 창 함수는 창에서 각 행의 값을 계산합니다. 함수와 함께 OVER 절을 사용하여 이동 평균, 누적 집계, 누적 합계 합계 또는 그룹 결과 별 상위 N과 같은 집계 된 값을 계산할 수 있습니다. 행의 수는 감소하지 않습니다에 의해

파티션은

우리가 예를 들어 테이블에 의해 파티션을 적용 할 수 있습니다을 반환

select SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname from TableA 

결과 : 상기

marksum firstname 
------------------- 
134  arun      
134  arun      
134  arun      
94  ann      
94  ann      
41  sruthy     
47  new 

보기 결과는 그룹화 된 행과 결과가 아닌 모든 행을 분할합니다.

+1

'SUM (Mark) OVER (PARTITION BY id) AS marksum ... '을 선택한다고 생각합니다. – mbomb007

+1

'partition by' *은 행 수에 영향을 미칠 수 있습니다. – John

+0

@ John이 의견을 주셔서 감사합니다. –

-1
-- BELOW IS A SAMPLE WHICH OUTLINES THE SIMPLE DIFFERENCES 
-- READ IT AND THEN EXECUTE IT 
-- THERE ARE THREE ROWS OF EACH COLOR INSERTED INTO THE TABLE 
-- CREATE A database called testDB 


-- use testDB 
USE [TestDB] 
GO 


-- create Paints table 
CREATE TABLE [dbo].[Paints](
    [Color] [varchar](50) NULL, 
    [glossLevel] [varchar](50) NULL 
) ON [PRIMARY] 

GO 


-- Populate Table 
insert into paints (color, glossLevel) 
select 'red', 'eggshell' 
union 
select 'red', 'glossy' 
union 
select 'red', 'flat' 
union 
select 'blue', 'eggshell' 
union 
select 'blue', 'glossy' 
union 
select 'blue', 'flat' 
union 
select 'orange', 'glossy' 
union 
select 'orange', 'flat' 
union 
select 'orange', 'eggshell' 
union 
select 'green', 'eggshell' 
union 
select 'green', 'glossy' 
union 
select 'green', 'flat' 
union 
select 'black', 'eggshell' 
union 
select 'black', 'glossy' 
union 
select 'black', 'flat' 
union 
select 'purple', 'eggshell' 
union 
select 'purple', 'glossy' 
union 
select 'purple', 'flat' 
union 
select 'salmon', 'eggshell' 
union 
select 'salmon', 'glossy' 
union 
select 'salmon', 'flat' 


/* COMPARE 'GROUP BY' color to 'OVER (PARTITION BY Color)' */ 

-- GROUP BY Color 
-- row quantity defined by group by 
-- aggregate (count(*)) defined by group by 
select count(*) from paints 
group by color 

-- OVER (PARTITION BY... Color 
-- row quantity defined by main query 
-- aggregate defined by OVER-PARTITION BY 
select color 
, glossLevel 
, count(*) OVER (Partition by color) 
from paints 

/* COMPARE 'GROUP BY' color, glossLevel to 'OVER (PARTITION BY Color, GlossLevel)' */ 

-- GROUP BY Color, GlossLevel 
-- row quantity defined by GROUP BY 
-- aggregate (count(*)) defined by GROUP BY 
select count(*) from paints 
group by color, glossLevel 



-- Partition by Color, GlossLevel 
-- row quantity defined by main query 
-- aggregate (count(*)) defined by OVER-PARTITION BY 
select color 
, glossLevel 
, count(*) OVER (Partition by color, glossLevel) 
from paints 
0

생각에는 우리는 14

즉 단일 행에 수를 줄 만의 것

group by

select name,count(*) as totalcount from person where name='Please fill out' group BY name; 

테이블에 name 열 (14 개) 기록이 partition by

select row_number() over (partition by name) as total from person where name = 'Please fill out'; 

카운트가 14 행 증가합니다

0

작은 관찰. 자동화 메커니즘을 사용하여 '파티션 by by'을 사용하여 SQL을 동적으로 생성하면 'group by'과 관련하여 구현하는 것이 훨씬 간단합니다. '그룹화'의 경우 '선택'열의 내용을 처리해야합니다.

죄송합니다.