Esecuzione totale alla riga precedente


14

Ho bisogno di aiuto con le funzioni di windowing. So che puoi calcolare la somma all'interno di una finestra e il totale parziale all'interno di una finestra. Ma è possibile calcolare il totale parziale precedente, cioè il totale parziale senza la riga corrente?

Suppongo che dovresti usare l' argomento ROWo RANGE. So che esiste CURRENT ROWun'opzione, ma avrei bisogno CURRENT ROW - 1, che è una sintassi non valida. La mia conoscenza degli argomenti ROWe RANGEè limitata, quindi qualsiasi aiuto sarebbe ricevuto con gratitudine.

So che ci sono molte soluzioni a questo problema, ma sto cercando di capire gli argomenti ROW, RANGEe presumo che il problema possa essere risolto con questi. Ho incluso un modo possibile per calcolare il totale parziale precedente ma mi chiedo se esiste un modo migliore:

USE AdventureWorks2012

SELECT s.SalesOrderID
    , s.SalesOrderDetailID
    , s.OrderQty
    , SUM(s.OrderQty) OVER (PARTITION BY  SalesOrderID) AS RunningTotal
    , SUM(s.OrderQty) OVER (PARTITION BY  SalesOrderID 
                         ORDER BY SalesOrderDetailID) - s.OrderQty AS PreviousRunningTotal
    -- Sudo code - I know this does not work
    --, SUM(s.OrderQty) OVER (PARTITION BY  SalesOrderID 
    --                   ORDER BY SalesOrderDetailID
    --                   ROWS BETWEEN UNBOUNDED PRECEDING 
    --                                   AND CURRENT ROW - 1) 
    -- AS  SudoCodePreviousRunningTotal
FROM Sales.SalesOrderDetail s
WHERE SalesOrderID IN (43670, 43669, 43667, 43663)
ORDER BY s.SalesOrderID
    , s.SalesOrderDetailID 
    , s.OrderQty

Risposte:


22

La risposta è usare 1 PRECEDING, no CURRENT ROW -1. Quindi, nella tua query, usa:

    , SUM(s.OrderQty) OVER (PARTITION BY  SalesOrderID 
                            ORDER BY SalesOrderDetailID
                            ROWS BETWEEN UNBOUNDED PRECEDING 
                                     AND 1 PRECEDING) 
    AS  PreviousRunningTotal

Si noti inoltre che sull'altro calcolo:

    , SUM(s.OrderQty) OVER (PARTITION BY  SalesOrderID
                            ORDER BY SalesOrderDetailID) ...

SQL Server utilizza l'impostazione predefinita * RANGE UNBOUNDED PRECEDING AND CURRENT ROW . Penso che ci sia una differenza di efficienza ROWS UNBOUNDED PRECEDING AND CURRENT ROWda preferire (dopo il test ovviamente e se fornisce i risultati desiderati).

Molti altri dettagli sono disponibili nell'articolo del blog di @Aaron Bertrand , inclusi i test delle prestazioni: i migliori approcci per l'esecuzione dei totali - aggiornato per SQL Server 2012

* questo è ovviamente l'intervallo predefinito quando ORDER BYè presente un all'interno della OVERclausola - altrimenti, senza ORDER BYl'impostazione predefinita è l'intera partizione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.