SQL Server: PARTITION BY ve GROUP BY arasındaki fark


366

GROUP BYYıllar boyunca her türlü toplu sorgulama için kullanıyorum . Son zamanlarda, PARTITION BYtoplama yapmak için kullanılan bazı kodları tersine mühendislik yaptım . Bulduğum tüm belgeleri okurken , belki biraz ekstra işlevsellik eklenmiş PARTITION BYgibi GROUP BY, kulağa çok benziyor ? Aynı genel işlevselliğin iki sürümü mü yoksa tamamen farklı bir şey mi?

Yanıtlar:


441

Farklı yerlerde kullanılırlar. group bytüm sorguyu değiştirir, örneğin:

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

Ancak , aşağıdaki gibi bir pencere işlevipartition by üzerinde çalışır :row_number

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

A group bynormalde, bunları yuvarlayarak ve her satır için ortalamaları veya toplamları hesaplayarak döndürülen satır sayısını azaltır. partition bydöndürülen satır sayısını etkilemez, ancak bir pencere işlevinin sonucunun nasıl hesaplandığını değiştirir.


23
güzel cevap, lütfen her biri için döndürülen sonuçların bir örneğini yazar mısınız?
Ashkan Mobayen Khiabani

2
@AshkanMobayenKhiabani, sql server sürümünüze bağlı olarak varsayılan olarak kurulabilecek veya yüklenmeyecek her iki sorguyu da Northwind'e karşı çalıştırabilirsiniz. Değilse, indirilenler sayfasında arayabilirsiniz.
Fetchez la vache

15
@AshkanMobayenKhiabani Arunprasanth'ın cevabı, daha fazla öğrenme çemberinden atlamak yerine zamandan tasarruf edebileceğiniz ve Northwind
Praxiteles

1
Windows işlevleri hakkında daha fazla bilgi (SQL'de): blog.jooq.org/2013/11/03/…
datps

itcodehub.blogspot.com/2019/03/… - sql tarafından gruplama ve bölümleme arasındaki farklar hakkında daha fazla bilgi ve örnek
xproph

252

Basit bir örnek alabiliriz.

TableAAşağıdaki değerlerle adlandırılmış bir tablo düşünün :

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

SQL GROUP BY deyimi, bir SELECT deyiminde birden çok kayıtta veri toplamak ve sonuçları bir veya daha fazla sütuna göre gruplamak için kullanılabilir.

Daha basit bir deyişle, GROUP BY deyimi, sonuç kümesini bir veya daha fazla sütuna göre gruplandırmak için toplama işlevleriyle birlikte kullanılır.

Sözdizimi:

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

GROUP BYMasamıza başvurabiliriz :

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

Sonuçlar:

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

Gerçek tablomuzda 7 satır var ve uyguladığımızda GROUP BY id, sunucu sonuçları aşağıdakilere göre gruplandırıyor id:

Basit bir ifadeyle:

burada GROUP BYnormalde Sum(), her bir satır için toplanarak ve hesaplanarak döndürülen satır sayısını azaltır .

PARTITION BY

PARTITION BY bölümüne gitmeden önce, OVERmaddeye bakalım :

MSDN tanımına göre:

OVER yan tümcesi, sorgu sonuç kümesindeki bir pencereyi veya kullanıcı tarafından belirtilen satır kümesini tanımlar. Bir pencere işlevi, penceredeki her satır için bir değer hesaplar. OVER yan tümcesini, hareketli ortalamalar, kümülatif toplamalar, çalışan toplamlar veya grup başına en üstteki N gibi toplanmış değerleri hesaplamak için işlevlerle birlikte kullanabilirsiniz.

PARTITION BY, döndürülen satır sayısını azaltmaz.

PARTITION BY öğesini örnek tablonuza uygulayabiliriz:

SELECT SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname FROM TableA

Sonuç:

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

Sonuçlara bakın - GROUP BY'ın aksine satırları bölümler ve tüm satırları döndürür .


3
partition by olabilir satır sayısını etkileyen, sadece alışkanlık azaltmak satır sayısını.
John

1
İ değiştirmek olsaydı fark ne olurdu SELECTINTO SELECT DISTINCTikinci sorguya? GROUP BYsorguyla aynı veri kümesini döndürmez mi? Birini veya diğerini seçmenin nedenleri nelerdir?
Erick 3E

3
@ Erick3E lütfen bu soruya bir göz atın stackoverflow.com/questions/20375074/…
Arunprasanth KV

Bu cevabı daha çok seviyorum çünkü Toplama fonksiyonlarının Min / Maks / Toplam vb. Row_Number () örneği bunu netleştirmiyor. Normalde GROUP BY ile bir toplama işlevi kullanıyorum ama PARTITION-OVER'ın aynı yöntemlere sahip olduğunu fark ettim ve OP'nin yaptığı aynı şeyi merak ettim. Teşekkürler!
ripvlan

53

partition byaslında verileri toplamaz. Grup başına bir şeyi sıfırlamanızı sağlar. Örneğin, gruplama alanına bölümleme yaparak ve rownum()o gruptaki satırları kullanarak bir grup içinde sıralı sütun alabilirsiniz . Bu, her grubun başında sıfırlanan bir kimlik sütunu gibi davranan bir şey verir.


43

BÖLME TARAFI Sonuç kümesini bölümlere ayırır. Pencere işlevi her bir bölüme ayrı ayrı uygulanır ve her bölüm için hesaplama yeniden başlar.

Bu bağlantıda bulundu: OVER yan tümcesi


36

Yuvarlanmadan toplanmış veriler sağlar

Yani satış bölgesinin göreli konumunu geri döndürmek istediğimi varsayalım

PARTITION BY kullanarak, belirli bir bölgenin satış tutarını iade edebilir ve aynı satırdaki tüm satış bölgelerde MAX miktarı.

Bu, tekrarlanan verilere sahip olacağınız anlamına gelir, ancak GROUP BY ile olduğu gibi verilerin toplandığı ancak hiçbir veri kaybedilmediği anlamında son tüketiciye uygun olabilir.


3
En iyi, en basit cevap.
tmthyjames

27

PARTITION BYanalitikken, GROUP BYtoplamdır. Kullanım için PARTITION BY, bir ile içermek zorunda AŞIRI maddesi .


1
PARTITION BY is analyticbu basit ifade benim için çok şey düzeltti. +1.

Bu aslında en basit ve en iyi cevap.
jdmneon

22

Anladığım kadarıyla Partition By, Group By ile neredeyse aynı, ancak aşağıdaki farklarla:

Bu grup, sonuç kümesini grup başına bir satır döndürerek sonuç olarak gruplandırır, bu nedenle SQL Server'da yalnızca SELECT listesinde toplama işlevlerine veya grubun bir parçası olan sütunlara (bu durumda SQL Server benzersiz olduğunu garanti edebilir) izin verir. her grup için sonuçlar).

Örneğin, Grupla yan tümcesinde tanımlı olmayan SELECT liste sütunlarında bulunmasına izin veren MySQL'i düşünün, bu durumda grup başına bir satır hala döndürülür, ancak sütun benzersiz sonuçlar içermiyorsa, garanti yoktur çıktı ne olacak!

Ancak Partition By ile, işlevin sonuçları Group By ile bir toplu işlevin sonuçlarıyla özdeş olmasına rağmen, yine de normal sonuç kümesini alıyorsunuz, yani altta yatan satır başına bir satır alıyor, grubundan ve bu nedenle SELECT listesinde grup başına benzersiz olmayan sütunlar olabilir.

Özet olarak, Gruplama, grup başına bir satır çıktısı gerektiğinde en iyi olur ve Bölümleme, tüm satırlara ihtiyaç duyduğunda ancak yine de bir gruba dayalı toplama işlevini istediğinde en iyi olur.

Elbette performans sorunları da olabilir, bkz. Http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba .


2

Kullandığınızda GROUP BY, elde edilen satırlar genellikle gelen satırlardan daha az olur.

Ancak, kullandığınızda PARTITION BY, elde edilen satır sayısı gelenle aynı olmalıdır.


0

nameTabloda 14 sütun kaydımız olduğunu varsayalım

içinde group by

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

tek satırda sayım verir, yani 14

ama içinde partition by

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

sayımda 14 sıra artış olacak


0

Küçük gözlem. 'Partition by' kullanarak dinamik olarak SQL üretmek için otomasyon mekanizması 'group by' ile ilişkili olarak uygulamak çok daha kolaydır. 'Gruplama ölçütü' durumunda, 'seçme' sütununun içeriğine dikkat etmeliyiz.

İngilizcem için üzgünüm.


0

Gerçekten farklı kullanım senaryoları var. GROUP BY kullandığınızda, aynı olan sütunların bazı kayıtlarını birleştirirsiniz ve sonuç kümesini toplarsınız.

Ancak PARTITION BY sonuç kümenizi kullandığınızda, ancak pencere işlevleri üzerinde bir toplama işleminiz olduğunda ve kayıtları birleştirmediğinizde, yine de aynı sayıda kayıt elde edersiniz.

İşte farkı açıklayan bir ralli yardımcı makalesi: 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.