2012-01-13 63 views
4

數據庫有一個transactions表,其中列爲:account_iddatetransaction_value(有符號整數)。另一個表(account_value)存儲每個帳戶的當前總值,即每個帳戶的所有transaction_value s的總和。它與在transactions表的觸發更新(即插入,更新和刪除操作transactions火觸發改變account_value。)高效滑動窗口總和數據庫表

一個新的要求僅僅是在過去的365來計算賬戶的交易總價值。只需要當前的運行總數,而不是先前的總數。這個值經常被要求,幾乎和account_value一樣多。

你將如何實現這個「活動窗口和」有效?新表可以。有沒有辦法避免每次總結一年的時間?

+0

哪個版本的SQL? – MatBailie 2012-01-13 09:27:01

+0

你是否保留了一年中所有不同日子的所有運行總數記錄?這樣你可以在一個報告中看到整個月的價值? – MatBailie 2012-01-13 09:53:32

+0

爲了解釋Dems,你是否僅僅想要「距離今天過去365天」,或者你想「在其他某個範圍內每天的最後365天」? – gbn 2012-01-13 10:06:17

回答

1

這樣簡單?

SELECT 
    SUM(transaction_value), account_id 
FROM 
    transactions t 
WHERE 
    -- SQL Server, Sybase  t.DATE >= DATEADD(year, -1, GETDATE()) 
    -- MySQL   t.DATE >= DATE_SUB(NOW(), INTERVAL 12 MONTH) 
GROUP BY 
    account_id; 

您可能希望在SQL Server中使用DATE(MySQL的)或this way日期表達式刪除時間部分

+0

+1每年總結一年的範圍並不是那麼糟糕! – 2012-01-13 09:32:23

+1

Sybase ASE也是第一個:P – 2012-01-13 09:32:55

+1

@aF。我想OP希望每天都有一份報告顯示year_to_date的總運行時間。因此,涵蓋一年的報告將在365天不同的範圍內有365個不同的總計,並且這是每個帳戶。這真是一個頭痛的問題,如果經常更有效,基於觸發器的當前值緩存。 – MatBailie 2012-01-13 09:48:33

1

如果交易表的查詢比插入到事務表更加頻繁,則或許一種觀點是要走的路?

+1

還是妥協:物化視圖或索引視圖,取決於有問題的RDBMS? – 2012-01-13 09:42:52

+1

運行總計非常昂貴。這種基於觸發器的方法將使用較少的資源來進行直接查詢,即使讀取次數比寫入次數少100次。 – MatBailie 2012-01-13 09:44:37

+1

但是基於觸發器的方法不能保證總數是正確的。 – 2012-01-13 23:44:25

0

您將需要一個一次性的腳本來用前一年爲每個現有的記錄值現有的表 - 這將需要整個前一年的每個記錄生成的運行。

填充滾動年份列後,對前一年進行總計的一種替代方法是將每個新記錄的值作爲上一個記錄的滾動年份值加上自上次更新以來的事務值減去事務從最近一次更新之前的一年到現在的一年之前的值。

我建議嘗試這兩種方法對現實的測試數據,看哪個會更好 - 我期望總結一年至少執行至少以及數據相對稀疏,而差異的方法可能會更好地工作,如果數據是經常更新每個帳戶。

0

我會避免任何實際的SQL這裏,因爲它取決於各種SQL的您正在使用差異很大。


你說你有一個觸發維持現有的運行總量。

我相信,它也(或者夜間處理過程)會在account_value表新的每日記錄。然後INSERT,UPDATE和DELETE觸發觸發器來添加或減去現有的運行總數?

只有你需要做的變化是:
- 增加一個新的領域,「yearly_value」什麼
- 有一個現有的觸發更新,在相同的方式,現有的場地
- 利用GBN的類型回答創建今天的記錄(或者你回溯到最遠)
- 但以稍微不同的方式初始化每個新的日誌...

當您爲新的一天插入新行時,應將其初始化爲yesterday's value - the value 365 days ago。之後,行爲應該與你已經習慣的相同。

1

這可以用標準的窗函數來完成:

SELECT account_id, 
     sum(transaction_value) over (partition by account_id order by date) 
FROM transactions 

order byover() claues內,使之和「滑動求和」。

對於「只有最後356天」,您需要第二個查詢來限制WHERE子句中的行。

上述工作在PostgreSQL,Oracle,DB2和(我認爲)Teradata。 SQL Server不支持在窗口定義中的順序(即將推出的Denali版本將AFAIK)

+0

僅供參考,您對使用聚合函數的SQL Server中的OVER子句限制是正確的。只有PARTITION BY可以使用 – gbn 2012-01-13 09:47:26

+0

@gbn:你的意思是SQL Server? – 2012-01-13 09:48:09

+0

是的,編輯了評論 – gbn 2012-01-13 09:49:24