2010-03-08 85 views
233

Tôi đã sử dụng GROUP BY cho tất cả các loại truy vấn tổng hợp trong những năm qua. Gần đây, tôi đã đảo ngược kỹ thuật một số mã sử dụng PARTITION BY để thực hiện tổng hợp. Khi đọc qua tất cả tài liệu tôi có thể tìm thấy khoảng PARTITION BY, nó nghe có vẻ giống như GROUP BY, có thể với một chút chức năng bổ sung được thêm vào? Có phải họ là hai phiên bản của cùng một chức năng chung, hoặc chúng là một cái gì đó hoàn toàn khác nhau?Máy chủ SQL: Sự khác biệt giữa PARTITION BY và GROUP BY

Trả lời

270

Chúng được sử dụng ở những nơi khác nhau. group by đổi các truy vấn toàn bộ, như:

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

Nhưng partition by chỉ hoạt động trên a window function, như row_number:

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

Một group by thường làm giảm số lượng hàng trả lại bằng cách lăn chúng lên và tính trung bình hoặc tiền Cho mỗi hàng. partition by không ảnh hưởng đến số hàng được trả về, nhưng nó thay đổi cách tính kết quả của hàm cửa sổ.

+8

câu trả lời hay, bạn vui lòng viết một mẫu kết quả trả về cho mỗi người trong số họ không? –

+2

@AshkanMobayenKhiabani bạn có thể chạy cả hai truy vấn đối với Northwind, có thể hoặc không được cài đặt theo mặc định tùy thuộc vào phiên bản máy chủ sql của bạn. Nếu không, bạn có thể tìm kiếm nó trên trang tải xuống. –

+9

@AshkanMobayenKhiabani Câu trả lời của Arunprasanth dưới đây cho thấy kết quả trả về có thể giúp bạn tiết kiệm thời gian thay vì nhảy qua nhiều vòng học và thời gian học Northwind – Praxiteles

42

partition by không thực sự cuộn lên dữ liệu. Nó cho phép bạn thiết lập lại một cái gì đó trên một cơ sở cho mỗi nhóm. Ví dụ, bạn có thể lấy một cột thứ tự trong một nhóm bằng cách phân vùng trên trường nhóm và sử dụng rownum() trên các hàng trong nhóm đó. Điều này cung cấp cho bạn một cái gì đó mà cư xử một chút giống như một cột nhận dạng mà đặt lại ở đầu mỗi nhóm.

20

PARTITION BY là phân tích, trong khi GROUP BY là tổng hợp. Để sử dụng PARTITION BY, bạn phải chứa nó với OVER clause.

+0

'PARTITION BY là giải tích' câu lệnh đơn giản này đã xóa rất nhiều cho tôi. +1. –

33

PARTITION BY Chia tập hợp kết quả thành phân vùng. Chức năng cửa sổ được áp dụng cho từng phân vùng riêng biệt và khởi động lại tính toán cho mỗi phân vùng.

Tìm thấy tại liên kết này: OVER Clause

22

Nó cung cấp dữ liệu cuộn lên mà không lăn lên

tức Giả sử tôi muốn quay trở lại vị trí tương đối của khu vực bán hàng

Sử dụng PARTITION BY, tôi có thể trả lại số tiền bán hàng cho một khu vực nhất định số tiền MAX trên tất cả các khu vực bán hàng trong cùng một hàng. Điều này có nghĩa là bạn sẽ có dữ liệu lặp lại, nhưng nó có thể phù hợp với người tiêu dùng cuối cùng theo nghĩa là dữ liệu đã được tổng hợp nhưng không có dữ liệu nào bị mất - như trường hợp của GROUP BY.

+0

Câu trả lời hay nhất, đơn giản nhất. – tmthyjames

18

Tính đến hiểu biết của tôi Partition Bằng là gần như giống hệt Nhóm Bằng, nhưng với sự khác biệt sau:

Đó nhóm bằng cách thực sự nhóm kết quả thiết lập trở lại một hàng cho mỗi nhóm, mà do đó dẫn đến SQL Server chỉ cho phép trong danh sách SELECT tổng hợp các hàm hoặc các cột là một phần của nhóm theo mệnh đề (trong trường hợp này SQL Server có thể đảm bảo rằng có các kết quả duy nhất cho mỗi nhóm).Hãy xem xét ví dụ MySQL cho phép có trong cột danh sách SELECT không được định nghĩa trong mệnh đề Nhóm theo, trong trường hợp một hàng vẫn được trả về cho mỗi nhóm, tuy nhiên nếu cột không có kết quả duy nhất thì không có gì đảm bảo sẽ là đầu ra! Tuy nhiên, với Partition By, mặc dù kết quả của hàm giống hệt với kết quả của một hàm tổng hợp với Group By, bạn vẫn nhận được tập kết quả bình thường, có nghĩa là một kết quả nhận được một hàng cho mỗi hàng bên dưới, và không phải một hàng cho mỗi nhóm và vì nhóm này có thể có các cột không phải là duy nhất cho mỗi nhóm trong danh sách SELECT. Vì vậy, như là một bản tóm tắt, Group By sẽ là tốt nhất khi cần một đầu ra của một hàng cho mỗi nhóm, và phân vùng theo sẽ là tốt nhất khi một nhu cầu tất cả các hàng nhưng vẫn muốn chức năng tổng hợp dựa trên một nhóm.

Tất nhiên cũng có thể có vấn đề về hiệu suất, xem http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba.

127

Chúng ta có thể lấy một ví dụ đơn giản

chúng tôi có một bảng tên TableA với các giá trị sau.

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 

Nhóm By

Các GROUP BY khoản SQL có thể được sử dụng trong một câu lệnh SELECT để thu thập dữ liệu trên nhiều hồ sơ và nhóm kết quả theo một hoặc nhiều cột.

Nói một cách đơn giản Câu lệnh GROUP BY được sử dụng kết hợp với các hàm tổng hợp để nhóm nhóm kết quả theo một hoặc nhiều cột .

cú pháp:

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

Chúng ta có thể áp dụng groupby trong bảng của chúng tôi

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

Kết quả:

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

Trong bảng thực, chúng ta có 7 hàng và khi chúng tôi áp dụng nhóm theo id , Nhóm máy chủ kết quả dựa trên id

Nói cách đơn giản

đây nhóm bằng cách thường làm giảm số lượng hàng trả lại do cán họ lên và tính Sum cho mỗi hàng.

phân vùng bởi

trước khi đi phân vùng bởi

chúng ta hãy nhìn vào VỀ khoản

Theo MSDN nét

VỀ khoản định nghĩa một cửa sổ hoặc tập hợp các hàng được chỉ định bởi wi thin a bộ kết quả truy vấn. Hàm cửa sổ sau đó tính giá trị cho mỗi hàng trong cửa sổ. Bạn có thể sử dụng mệnh đề OVER với các hàm để tính các giá trị tổng hợp, chẳng hạn như số trung bình động, tổng hợp lũy tích, tổng số đang chạy hoặc kết quả N trên cùng cho mỗi kết quả nhóm.

phân vùng bằng cách sẽ không làm giảm số lượng hàng trả lại

chúng ta có thể áp dụng phân vùng bởi trong bảng ví dụ của chúng

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

kết quả:

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

nhìn vào kết quả nó sẽ phân chia các hàng và kết quả tất cả các hàng không giống như nhóm theo.

+1

Tôi nghĩ rằng bạn có nghĩa là 'chọn SUM (Mark) OVER (PARTITION BY id) AS marksum ...' – mbomb007

+1

'phân vùng bởi' * có thể * ảnh hưởng đến số hàng, nó sẽ không * giảm * số hàng. – John

+0

@John cảm ơn cho nhận xét, bài chỉnh sửa –

-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

Giả sử chúng ta có 14 hồ sơ của name cột trong bảng

trong group by

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

nó sẽ cho đếm trong hàng duy nhất tức là 14

nhưng trong partition by

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

nó sẽ tăng 14 hàng đếm

0

Quan sát nhỏ. Cơ chế tự động hóa để tạo động SQL bằng cách sử dụng 'phân vùng theo' nó đơn giản hơn nhiều để thực hiện liên quan đến 'nhóm theo'. Trong trường hợp 'nhóm theo', chúng ta phải chăm sóc nội dung của cột 'chọn'.

Xin lỗi vì tiếng Anh của tôi.