Total berjalan ke baris sebelumnya

14

Saya butuh bantuan dengan fungsi windowing. Saya tahu Anda bisa menghitung jumlah di dalam jendela dan total yang berjalan di dalam jendela. Tetapi apakah mungkin untuk menghitung total running sebelumnya yaitu total running tidak termasuk baris saat ini?

Saya menganggap Anda perlu menggunakan argumen ROWatau RANGE. Saya tahu ada CURRENT ROWopsi tapi saya perlu CURRENT ROW - 1, yang sintaks tidak valid. Pengetahuan saya tentang ROWdan RANGEargumen terbatas sehingga bantuan apa pun akan diterima dengan penuh syukur.

Saya tahu bahwa ada banyak solusi untuk masalah ini, tetapi saya ingin memahami ROW, RANGEargumen dan saya berasumsi masalahnya dapat dipecahkan dengan ini. Saya telah memasukkan satu cara yang mungkin untuk menghitung total berjalan sebelumnya tetapi saya bertanya-tanya apakah ada cara yang lebih baik:

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

Jawaban:

22

Jawabannya adalah menggunakan 1 PRECEDING, bukan CURRENT ROW -1. Jadi, dalam kueri Anda, gunakan:

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

Perhatikan juga pada perhitungan Anda yang lain:

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

SQL-Server menggunakan default * RANGE UNBOUNDED PRECEDING AND CURRENT ROW . Saya pikir ada perbedaan efisiensi dan ROWS UNBOUNDED PRECEDING AND CURRENT ROWlebih disukai (setelah pengujian tentu saja dan jika memberikan hasil yang Anda inginkan).

Lebih banyak detail yang dapat Anda temukan di artikel blog oleh @ Harun Bertrand , termasuk tes kinerja: Pendekatan terbaik untuk menjalankan total - diperbarui untuk SQL Server 2012

* ini tentu saja kisaran default ketika ORDER BYada di dalam OVERklausa - jika tidak, tanpa ORDER BYdefault adalah seluruh partisi.

ypercubeᵀᴹ
sumber