SQL Server: Sự khác biệt giữa THAM GIA BỞI và NHÓM B BYNG


366

Tôi đã sử dụng GROUP BYcho tất cả các loại truy vấn tổng hợp trong nhiều năm qua. Gần đây, tôi đã thiết kế ngược một số mã sử dụng PARTITION BYđể thực hiện tổng hợp. Khi đọc qua tất cả các tài liệu tôi có thể tìm thấy PARTITION BY, nghe có vẻ rất giống GROUP BY, có thể có thêm một chút chức năng được thêm vào? Đây có phải 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?

Câu trả lời:


441

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

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

Nhưng partition bychỉ hoạt động trên một chức năng cửa sổ , như row_number:

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

Thông group bythường sẽ giảm số lượng hàng được trả về bằng cách cuộn chúng lên và tính trung bình hoặc tổng cho mỗi hàng. partition bykhông ảnh hưởng đến số lượng hàng được trả về, nhưng nó thay đổi cách tính kết quả của hàm cửa sổ.


23
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 câu hỏi?
Ashkan Mobayen Khiabani

2
@AshkanMobayenKhiabani bạn có thể chạy cả hai truy vấn đối với Northwind, có thể hoặc không thể 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.
Fetchez la vache

15
Câu trả lời của @AshkanMobayenKhiabani 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 tập và thời gian để học Northwind
Praxiteles

1
Thông tin thêm về các chức năng của windows (bằng SQL): blog.jooq.org/2013/11/03/ Từ
datps 7/2/2016

itcodehub.blogspot.com/2019/03/ Khăn - thêm thông tin và ví dụ về sự khác biệt giữa nhóm theo và phân vùng theo sql
xproph

252

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

Xem xét một bảng có tên TableAvớ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

GROUP BY

Mệnh đề SQL GROUP BY có thể được sử dụng trong câu lệnh CHỌN để thu thập dữ liệu trên nhiều bản ghi và nhóm kết quả theo một hoặc nhiều cột.

Nói một cách đơn giản hơn, câu lệnh GROUP BY được sử dụng cùng với các hàm tổng hợp để nhóm tập hợp 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 tôi có thể áp dụng GROUP BYtrong bảng của chúng tôi:

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

Các kết quả:

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

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

Nói một cách đơn giản:

ở đây GROUP BYthường làm giảm số lượng hàng trả về bằng cách cuộn chúng lại và tính toán Sum()cho mỗi hàng.

PARTITION BY

Trước khi đi đến PHẦN THAM GIA, chúng ta hãy xem OVERmệnh đề:

Theo định nghĩa MSDN:

Mệnh đề OVER xác định một cửa sổ hoặc tập hợp các hàng do người dùng chỉ định trong tập kết quả truy vấn. Sau đó, một hàm cửa sổ sẽ tính toán một giá trị cho mỗi hàng trong cửa sổ. Bạn có thể sử dụng mệnh đề QUÁ với các hàm để tính các giá trị tổng hợp, chẳng hạn như trung bình di chuyển, tổng gộp tích lũy, tổng số chạy hoặc kết quả N hàng đầu trên mỗi nhóm.

THAM GIA B BYNG sẽ không làm giảm số lượng hàng trả về.

Chúng ta có thể áp dụng THAM GIA B BYNG trong bảng ví dụ của mình:

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 vùng các hàng và trả về tất cả các hàng, không giống như NHÓM THEO.


3
partition by có thể ảnh hưởng đến số lượng hàng, nó sẽ không làm giảm số lượng hàng.
Giăng

1
Điều gì sẽ là sự khác biệt nếu tôi thay đổi SELECTthành SELECT DISTINCTtruy vấn thứ hai? sẽ không trả về cùng một tập dữ liệu như GROUP BYtruy vấn? Những lý do của việc chọn cái này hay cái kia là gì?
Erick 3E

3
@ Erick3E vui lòng xem qua câu hỏi này stackoverflow.com/questions/20375074/NH
Arunprasanth KV

Tôi thích câu trả lời này hơn vì nó cho thấy các hàm Tổng hợp tối thiểu / Tối đa / Tổng, v.v. hoạt động như thế nào trên Phân vùng. Ví dụ Row_Number () không làm cho nó rõ ràng. Thông thường tôi sử dụng một hàm tổng hợp với GROUP BY nhưng chỉ nhận thấy rằng PHẦN THAM GIA có cùng phương thức và tự hỏi điều tương tự mà OP đã làm - dẫn tôi đến đây. Cảm ơn!
ripvlan

53

partition bykhông thực sự cuộn dữ liệu. Nó cho phép bạn thiết lập lại một cái gì đó trên cơ sở mỗi nhóm. Ví dụ: bạn có thể nhận được 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ì đó hoạt động giống như một cột danh tính đặt lại ở đầu mỗi nhóm.


43

PHẦN THAM GIA Phân chia tập kết quả thành các 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 từng phân vùng.

Tìm thấy tại liên kết này: Điều khoản QUÁ


36

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

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

Sử dụng PHẦN THAM GIA B, NG, 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 không 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 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.


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

27

PARTITION BYlà phân tích, trong khi GROUP BYlà tổng hợp. Để sử dụng PARTITION BY, bạn phải chứa nó với mệnh đề QUÁ .


1
PARTITION BY is analytictuyên bố đơn giản này đã xóa rất nhiều cho tôi. +1.

Đây thực sự là câu trả lời đơn giản và tốt nhất.
jdmneon

22

Theo hiểu biết của tôi, phân vùng By gần giống với Group By, nhưng với những khác biệt sau:

Nhóm đó thực sự nhóm các nhóm kết quả trả về một hàng cho mỗi nhóm, do đó, SQL Server chỉ cho phép trong danh sách CHỌN hàm tổng hợp hoặc các cột là một phần của nhóm theo mệnh đề (trong trường hợp SQL Server có thể đảm bảo rằng có duy nhất kết quả cho mỗi nhóm).

Ví dụ, hãy xem xét MySQL cho phép có các cột trong danh sách CHỌN không được xác định 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 đầu ra sẽ là gì!

Nhưng với phân vùng By, mặc dù kết quả của hàm giống hệt với kết quả của hàm tổng hợp với Group By, nhưng bạn vẫn nhận được tập kết quả bình thường, điều đó có nghĩa là một hàng nhận được một hàng trên mỗi hàng bên dưới và không phải là một hàng trên mỗi 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 CHỌN.

Vì vậy, như 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 người cần tất cả các hàng nhưng vẫn muốn hàm 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 .


2

Khi bạn sử dụng GROUP BY, các hàng kết quả thường sẽ ít hơn các hàng đến.

Nhưng, khi bạn sử dụng PARTITION BY, số lượng hàng kết quả sẽ giống như đến.


0

Giả sử chúng ta có 14 bản ghi của namecột trong bảng

trong group by

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

nó sẽ đếm trong một hàng, 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


0

Quan sát nhỏ. Cơ chế tự động hóa để tự động tạo SQL bằng cách sử dụng 'phân vùng theo', việc thực hiện đơn giản hơn nhiều so với 'nhóm theo'. Trong trường hợp 'nhóm theo', Chúng tôi 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.


0

Nó có kịch bản sử dụng thực sự khác nhau. Khi bạn sử dụng NHÓM THEO, bạn hợp nhất một số bản ghi cho các cột giống nhau và bạn có tổng hợp các tập kết quả.

Tuy nhiên, khi bạn sử dụng PHẦN THAM GIA theo tập kết quả của bạn là như nhau nhưng bạn chỉ có một tập hợp qua các chức năng của cửa sổ và bạn không hợp nhất các bản ghi, bạn vẫn sẽ có cùng số lượng bản ghi.

Đây là một bài viết hữu ích giải thích sự khác biệt: http://alevryustemov.com/sql/sql-partition-by/


-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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.