Sql-Server
避免重複的 CASE 表達式
SELECT x, y, z, CASE WHEN COUNT (PH.header_id) OVER (PARTITION BY PL.header_id) NOT IN (null,0) THEN L_Count ELSE COUNT (PH.header_id) OVER (PARTITION BY PL.header_id) END as quantity
有沒有更有效的方法來寫這個?
我非常清楚它在一張大桌子上執行兩次計數。
不幸的是,我無法發布查詢計劃,因為我正在使用的使用者帳戶正在等待 SHOWPLAN 權限。
NOT IN 子句是一個附帶問題。感謝您對改進方法的評論回饋,但問題的重點是重複計數。
這裡有兩個問題:
- 程式碼是多餘的,因為視窗函式被輸入了兩次
- 擔心的是 SQL Server 將執行兩次計數,因為它被引用了兩次
首先,我們可以通過只計算該表達式一次來解決整潔方面的問題(我將從
NOT IN (NULL, 0)
邏輯更改為僅檢查計數是否大於 0(這消除了 NULL 和 0):;WITH x AS ( SELECT x, y, z, L_Count, q = COUNT (PH.header_id) OVER (PARTITION BY PL.header_id) FROM ...something PH and PL... ) SELECT x, y, z, quantity = CASE WHEN q > 0 THEN L_Count ELSE q END FROM x;
這是否是正確或最有效的分區選擇是另一回事。
其次,SQL Server 非常聰明,它只在給定範圍內執行一次計算。如上所述,兩次引用一個表達式並不一定意味著它會被計算兩次,並且像我在這個答案中所做的那樣將第二個引用隱藏在 CTE 中也不能保證它只會被計算一次。要確定,您必須檢查執行計劃和其他詳細資訊(如表達式選項卡和由計劃資源管理器提供的性能指標)並進行比較。
擁有表結構、樣本數據和期望的結果(甚至更多的查詢)將真正有助於為您創建更好的(和經過驗證的)解決方案。我只是建議你在你的問題中使用的相同邏輯,我只能假設它現在對你有用(我試圖理解你的
CASE
邏輯甚至意味著什麼 - 它似乎在說“如果有一個有效的計數來自此視窗函式,然後使用此另一列,但如果此視窗函式沒有有效計數,請使用無效計數")。我懷疑在翻譯/簡化中失去了一些東西。也可以看看:
- 我的文章CASE 表達式的骯髒秘密
- 我對 Stack Overflow 上一個相關問題的回答。
- Paul White計算標量、表達式和執行計劃性能。