Ricerca…


Parametri

Parametro Dettagli
PARTITION BY Il / i campo / i che segue PARTITION BY è quello su cui si baserà il 'raggruppamento'

Osservazioni

La clausola OVER determina una finestra o un sottoinsieme di righe all'interno di una serie di risultati della query. È possibile applicare una funzione finestra per impostare e calcolare un valore per ogni riga nel set. La clausola OVER può essere utilizzata con:

  • Funzioni di classificazione
  • Funzioni aggregate

quindi qualcuno può calcolare valori aggregati come medie mobili, aggregati cumulativi, totali parziali o risultati N migliori per gruppo.

In un modo molto astratto possiamo dire che OVER si comporta come GROUP BY. Tuttavia, OVER viene applicato per campo / colonna e non per la query nel suo complesso come fa GROUP BY.

Nota n. 1: in SQL Server 2008 (R2), la clausola ORDER BY non può essere utilizzata con le funzioni della finestra di aggregazione ( collegamento ).

Utilizzo delle funzioni di aggregazione con OVER

Usando la tabella Cars , calcoleremo l'importo totale, massimo, minimo e medio di denaro speso da ogni cliente e molte volte (COUNT) ha portato una macchina per ripararla.

Id CustomerId MechanicId Status Status Costo totale

SELECT CustomerId,  
       SUM(TotalCost) OVER(PARTITION BY CustomerId) AS Total,
       AVG(TotalCost) OVER(PARTITION BY CustomerId) AS Avg,
       COUNT(TotalCost) OVER(PARTITION BY CustomerId) AS Count,
       MIN(TotalCost) OVER(PARTITION BY CustomerId) AS Min,
       MAX(TotalCost) OVER(PARTITION BY CustomerId) AS Max
  FROM CarsTable
 WHERE Status = 'READY'

Fai attenzione che l'utilizzo di OVER in questo modo non aggregherà le righe restituite. La query sopra riportata restituirà quanto segue:

Identificativo del cliente Totale Avg Contare min Max
1 430 215 2 200 230
1 430 215 2 200 230

La / e riga / e duplicata / i potrebbe non essere quella utile ai fini della segnalazione.

Se si desidera semplicemente aggregare i dati, sarà meglio utilizzare la clausola GROUP BY insieme alle funzioni aggregate appropriate. Ad esempio:

SELECT CustomerId,  
       SUM(TotalCost) AS Total,
       AVG(TotalCost) AS Avg,
       COUNT(TotalCost) AS Count,
       MIN(TotalCost) AS Min,
       MAX(TotalCost)  AS Max
  FROM CarsTable
 WHERE Status = 'READY'
GROUP BY CustomerId

Somma cumulativa

Usando la Tabella delle vendite degli articoli, cercheremo di scoprire come le vendite dei nostri articoli stanno aumentando attraverso le date. Per fare ciò calcoleremo la somma cumulativa delle vendite totali per ordine dell'articolo entro la data di vendita.

SELECT item_id, sale_Date 
       SUM(quantity * price) OVER(PARTITION BY item_id ORDER BY sale_Date ROWS BETWEEN UNBOUNDED PRECEDING) AS SalesTotal
  FROM SalesTable

Utilizzo delle funzioni di aggregazione per trovare i record più recenti

Utilizzando il database delle biblioteche , cerchiamo di trovare l'ultimo libro aggiunto al database per ogni autore. Per questo semplice esempio, assumiamo un ID sempre crescente per ogni record aggiunto.

SELECT MostRecentBook.Name, MostRecentBook.Title
FROM ( SELECT Authors.Name,
              Books.Title,
              RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.Id DESC) AS NewestRank
       FROM Authors
       JOIN Books ON Books.AuthorId = Authors.Id
     ) MostRecentBook
WHERE MostRecentBook.NewestRank = 1

Invece di RANK, è possibile utilizzare altre due funzioni per ordinare. Nell'esempio precedente il risultato sarà lo stesso, ma danno risultati diversi quando l'ordine dà più righe per ogni grado.

  • RANK() : i duplicati ottengono lo stesso valore, il grado successivo prende in considerazione il numero di duplicati nel grado precedente
  • DENSE_RANK() : i duplicati ottengono lo stesso valore, il grado successivo è sempre superiore a quello precedente
  • ROW_NUMBER() : assegnerà a ciascuna riga un 'rank' unico, 'classifica' i duplicati casualmente

Ad esempio, se la tabella aveva una colonna non univoca CreationDate e l'ordine è stato eseguito in base a tale, la seguente query:

SELECT Authors.Name,
       Books.Title,
       Books.CreationDate,
       RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS RANK,
       DENSE_RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS DENSE_RANK,
       ROW_NUMBER() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS ROW_NUMBER,
FROM Authors
JOIN Books ON Books.AuthorId = Authors.Id

Potrebbe comportare:

Autore Titolo Data di creazione RANGO DENSE_RANK ROW_NUMBER
Autore 1 Prenota 1 22/07/2016 1 1 1
Autore 1 Prenota 2 22/07/2016 1 1 2
Autore 1 Prenota 3 21/07/2016 3 2 3
Autore 1 Prenota 4 21/07/2016 3 2 4
Autore 1 Prenota 5 21/07/2016 3 2 5
Autore 1 Prenota 6 2016/04/07 6 3 6
Autore 2 Prenota 7 2016/04/07 1 1 1

Dividere i dati in bucket ugualmente partizionati usando NTILE

Supponiamo che tu disponga di punteggi degli esami per diversi esami e che tu voglia dividerli in quartili per esame.

-- Setup data:
declare @values table(Id int identity(1,1) primary key, [Value] float, ExamId int)
insert into @values ([Value], ExamId) values
(65, 1), (40, 1), (99, 1), (100, 1), (90, 1), -- Exam 1 Scores
(91, 2), (88, 2), (83, 2), (91, 2), (78, 2), (67, 2), (77, 2) -- Exam 2 Scores

-- Separate into four buckets per exam:
select ExamId, 
       ntile(4) over (partition by ExamId order by [Value] desc) as Quartile, 
       Value, Id 
from @values 
order by ExamId, Quartile

I nostri dati sugli esami sono stati suddivisi in quartili per esame

ntile funziona alla grande quando hai davvero bisogno di un certo numero di secchi e ognuno è riempito all'incirca allo stesso livello. Si noti che sarebbe banale separare questi punteggi in percentili semplicemente usando ntile(100) .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow