Sök…


parametrar

Parameter detaljer
DELTAGNING AV Fältet / fälten som följer PARTITION BY är det som "gruppering" kommer att baseras på

Anmärkningar

OVER-klausulen bestämmer ett fönster eller en delmängd av raden i en sökresultatuppsättning. En fönsterfunktion kan tillämpas för att ställa in och beräkna ett värde för varje rad i uppsättningen. OVER-klausulen kan användas med:

  • Rankingfunktioner
  • Samlade funktioner

så att någon kan beräkna aggregerade värden som rörliga medelvärden, kumulativa aggregeringar, lösta totaler eller topp N per gruppresultat.

På ett mycket abstrakt sätt kan vi säga att ÖVER uppför sig som GROUP BY. Men OVER tillämpas per fält / kolumn och inte på frågan så hel som GROUP BY gör.

Obs # 1: I SQL Server 2008 (R2) ORDER BY-klausul kan inte användas med aggregerade fönsterfunktioner ( länk ).

Använda aggregeringsfunktioner med OVER

Med hjälp av biltabellen kommer vi att beräkna den totala, max, min och genomsnittliga summa pengar som varje kund använt och har många gånger (COUNT) som hon tog med sig en bil för reparation.

Id KundId Mekanisk Modell Status Total kostnad

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'

Se upp för att använda ÖVER på detta sätt inte kommer att samla de rader som returneras. Ovanstående fråga returnerar följande:

Kundnummer Total Avg Räkna min Max
1 430 215 2 200 230
1 430 215 2 200 230

De duplicerade raderna är kanske inte så användbara för rapporteringsändamål.

Om du bara vill aggregera data kommer du bättre att använda GROUP BY-klausulen tillsammans med lämpliga aggregerade funktioner, t.ex.

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

Kumulativ summa

Med hjälp av artikelförsäljningstabellen kommer vi att försöka ta reda på hur försäljningen av våra artiklar ökar genom datum. För att göra det kommer vi att beräkna den kumulativa summan av den totala försäljningen per artikelorder efter försäljningsdatumet.

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

Använd aggregeringsfunktioner för att hitta de senaste posterna

Med hjälp av biblioteksdatabasen försöker vi hitta den sista boken som lagts till i databasen för varje författare. För detta enkla exempel antar vi en alltid ökande id för varje post som läggs till.

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

I stället för RANK kan två andra funktioner användas för att beställa. I det föregående exemplet blir resultatet detsamma, men de ger olika resultat när beställningen ger flera rader för varje rang.

  • RANK() : dubbletter får samma rang, nästa rang tar hänsyn till antalet duplikat i föregående rang
  • DENSE_RANK() : duplikat får samma rang, nästa rang är alltid högre än föregående
  • ROW_NUMBER() : ger varje rad en unik 'rang', 'rangordnar' duplikaten slumpmässigt

Till exempel, om tabellen hade en icke-unik kolumn CreationDate och beställningen gjordes baserad på detta, följande fråga:

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

Kan resultera i:

Författare Titel Skapelsedagen RANG DENSE_RANK ROW_NUMBER
Författare 1 Bok 1 22/07/2016 1 1 1
Författare 1 Bok 2 22/07/2016 1 1 2
Författare 1 Bok 3 21/07/2016 3 2 3
Författare 1 Bok 4 21/07/2016 3 2 4
Författare 1 Bok 5 21/07/2016 3 2 5
Författare 1 Bok 6 2016/04/07 6 3 6
Författare 2 Bok 7 2016/04/07 1 1 1

Dela upp data i lika fördelade skopor med NTILE

Låt oss säga att du har betyg för flera tentor och att du vill dela upp dem i kvartiler per tentamen.

-- 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

Våra examensdata uppdelade i kvartiler per tentamen

ntile fungerar bra när du verkligen behöver ett fast antal hinkar och var och en fylls till ungefär samma nivå. Lägg märke till att det skulle vara trivialt att separera dessa poäng i percentiler genom att helt enkelt använda ntile(100) .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow