2010-03-08 18 views
233

Sto usando GROUP BY per tutti i tipi di query aggregate nel corso degli anni. Recentemente, ho eseguito il reverse engineering del codice che utilizza PARTITION BY per eseguire aggregazioni. Leggendo tutta la documentazione che posso trovare su PARTITION BY, suona molto come GROUP BY, forse con un po 'di funzionalità extra aggiunta? Sono due versioni della stessa funzionalità generale o sono qualcosa di completamente diverso?SQL Server: Differenza tra PARTITION BY e GROUP BY

risposta

270

Sono utilizzati in luoghi diversi. group by modifica la intera query, come:

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

Ma partition by solo funziona su a window function, come row_number:

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

Un group by riduce normalmente il numero di righe restituite da loro avvolgimento e calcolo delle medie o somme per ogni riga. partition by non influisce sul numero di righe restituite, ma modifica il modo in cui viene calcolato il risultato di una funzione della finestra.

+8

bella risposta, potresti scrivere un campione di risultati restituiti per ognuno di essi? –

+2

@AshkanMobayenKhiabani è possibile eseguire entrambe le query su Northwind, che può essere installata o meno in base alla versione del server sql. Altrimenti puoi cercarlo nella pagina dei download di s. –

+9

@AshkanMobayenKhiabani La risposta di Arunprasanth qui sotto mostra risultati restituiti che possono farti risparmiare tempo invece di saltare più anelli di apprendimento e tempo per imparare Northwind – Praxiteles

42

partition by non esegue il rollup dei dati. Ti permette di resettare qualcosa per gruppo. Ad esempio, è possibile ottenere una colonna ordinale all'interno di un gruppo mediante partizionamento sul campo di raggruppamento e utilizzando rownum() sulle righe all'interno di quel gruppo. Questo ti dà qualcosa che si comporta un po 'come una colonna di identità che si resetta all'inizio di ogni gruppo.

20

PARTITION BY è analitico, mentre GROUP BY è aggregato. Per utilizzare PARTITION BY, è necessario contenerlo con un OVER clause.

+0

'PARTITION BY is analytic' Questa semplice dichiarazione mi ha chiarito molto. +1. –

33

PARTITION BY Divide il set di risultati in partizioni. La funzione finestra viene applicata separatamente a ogni partizione e il calcolo ricomincia per ogni partizione.

trovate a questo link: OVER Clause

22

Fornisce dati raggruppati senza arrotolando

cioè Supponiamo che io voglio tornare la posizione relativa della regione di vendita

Utilizzando PARTITION BY, ho può restituire l'importo delle vendite per una data regione e l'importo MAX in tutte le aree di vendita nella stessa riga.

Ciò significa che i dati verranno ripetuti, ma potrebbero essere adatti al consumatore finale nel senso che i dati sono stati aggregati ma nessun dato è stato perso, come nel caso di GROUP BY.

+0

La migliore, la risposta più semplice. – tmthyjames

18

Al mia comprensione partizione è quasi identico al gruppo By, ma con le seguenti differenze:

Quel gruppo dalla realtà gruppi risultato impostato restituzione di una riga per gruppo, che si traduce quindi in SQL Server consentendo solo in l'elenco SELECT aggrega funzioni o colonne che fanno parte della clausola group by (nel qual caso SQL Server può garantire che vi siano risultati univoci per ciascun gruppo).

Consideriamo ad esempio MySQL che consente di avere nelle colonne dell'elenco SELECT non definite nella clausola Group By, nel qual caso una riga viene ancora restituita per gruppo, tuttavia se la colonna non ha risultati univoci, allora non c'è garanzia su quale sarà l'output!

Ma con Partition By, sebbene i risultati della funzione siano identici ai risultati di una funzione di aggregazione con Group By, si ottiene comunque il set di risultati normale, il che significa che si ottiene una riga per riga sottostante e non una riga per gruppo, e per questo motivo possono avere colonne che non sono univoche per gruppo nell'elenco SELECT.

Quindi, come riepilogo, Group By sarebbe il migliore quando è necessario un output di una riga per gruppo e Partition By sarebbe il migliore quando uno ha bisogno di tutte le righe ma vuole comunque la funzione di aggregazione basata su un gruppo.

Naturalmente potrebbero esserci problemi di prestazioni, vedere http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba.

127

possiamo prendere un semplice esempio

abbiamo una tabella denominata TableA con i seguenti valori.

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 

Raggruppa per

GROUP BY SQL può essere utilizzato in un'istruzione SELECT per raccogliere dati su più dischi e raggruppare i risultati di una o più colonne .

In parole più semplici l'istruzione GROUP BY viene utilizzata in combinazione con le funzioni di aggregazione per raggruppare il set di risultati mediante una o più colonne .

sintassi:

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

Possiamo applicare GroupBy nella nostra tabella

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

Risultati:

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

Nel nostro vero tavolo abbiamo 7 righe e quando applichiamo il gruppo per id , Il gruppo di server i risultati in base id

In parole semplici

qui gruppo dal normalmente riduce il numero di righe restituite rotolando loro e calcolando Sum per ogni riga.

partizione

prima di andare a partizionare da

guardiamo clausola OVER

Come da definizione MSDN

OLTRE clausola definisce una finestra o set di righe specificato dall'utente wi thin set di risultati della query . Una finestra funzione calcola quindi un valore per ogni riga nella finestra. È possibile utilizzare la clausola OVER con funzioni per calcolare valori aggregati come medie mobili, aggregati cumulativi, totali totali o N superiori per risultati di gruppo.

partizione non ridurrà il numero di righe restituite

possiamo applicare partizione nella nostra tabella di esempio

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

risultato:

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

sguardo al risultati partiziona le righe e risulta tutte le righe non come gruppo per.

+1

Penso che intendiate 'selezionare SUM (Mark) OVER (PARTITION BY id) AS markum ...' – mbomb007

+1

'partition by' * can * influenza il numero di righe, semplicemente non * riduce * il numero di righe. – John

+0

@John grazie per il commento, post modificato –

-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

Supponiamo di avere 14 dischi di name colonna in tabella

in group by

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

darà conteggio in singola fila cioè 14

ma in partition by

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

ci saranno 14 file di incremento nel conteggio

0

Piccola osservazione. Il meccanismo di automazione per generare dinamicamente SQL usando la 'partition by' è molto più semplice da implementare in relazione al 'group by'. Nel caso di "raggruppa per", dobbiamo occuparci del contenuto della colonna "seleziona".

Siamo spiacenti per il mio inglese.