T-Sql
在查詢期間更改值後組合以前不同的行
我目前正在執行一個查詢,該查詢應該返回按單個客戶分組的銷售人員的總收入。
由於處理使用者輸入的方式,有很多近乎重複的行,客戶端名稱有輕微的拼寫錯誤/添加。正如您在下面的程式碼中看到的那樣,我正在嘗試刪除其中一個問題字元串,以防止相同客戶端的重複行。
但是,儘管 CASE 語句成功刪除了“@iraPrefix”,但具有現在相同客戶名稱的行仍然沒有組合在一起,因為它們的收入欄位沒有被求和。
我應該如何處理這個?
DECLARE @iraPrefix VARCHAR(7) DECLARE @iraLen INT SET @iraPrefix = 'FOO BAR ' SET @iraLen = LEN(@iraPrefix) SELECT [client] = ( CASE SUBSTRING([name], 1, @iraLen) WHEN @iraPrefix THEN SUBSTRING([name], @iraLen+2, (LEN([name]) - @iraLen)) ELSE [name] END ) , CONCAT( sal.firstname , ' ' , sal.lastname) AS [salesman] , [revenue] = SUM(net)
以下是不刪除前綴的查詢結果範例:
目前查詢結果範例:
我想要的結果的一個例子:
再聚合一次。
你可以這樣做
- 實現中間結果集 (
SELECT ... INTO #intermediate FROM...
),然後聚合記憶體的中間結果- 將您目前的查詢包裝在一組括號中,並
SELECT
針對您分配給它的任何別名進行 ing。有關範例,請參見此小提琴。但是為了冗長,假設您的數據都儲存在一個名為 的表中
barfoo
,那麼您可以使用通用表表達式(或 CTE)執行此操作的一種方法是……DECLARE @iraPrefix VARCHAR(7); DECLARE @iraLen INT; SET @iraPrefix = 'FOO BAR '; SET @iraLen = LEN(@iraPrefix); WITH L1 AS ( SELECT [client] = ( CASE SUBSTRING([name], 1, @iraLen) WHEN @iraPrefix THEN SUBSTRING([name], @iraLen+2, (LEN([name]) - @iraLen)) ELSE [name] END ) , CONCAT( sal.firstname , ' ' , sal.lastname) AS [salesman] , [revenue] = SUM(net) FROM barfoo as sal GROUP BY [name],CONCAT( sal.firstname , ' ' , sal.lastname) ) SELECT [client], [salesman], SUM([revenue]) AS [revenue] FROM L1 GROUP BY [client], [salesman];
我喜歡使用 CTE 將清理和聚合步驟分開。這使得每一個都易於理解、更改和調試。就像是
; with Clean as ( SELECT [client] = ( CASE SUBSTRING([name], 1, @iraLen) WHEN @iraPrefix THEN SUBSTRING([name], @iraLen+2, (LEN([name]) - @iraLen)) ELSE [name] END ) , CONCAT( sal.firstname , ' ' , sal.lastname) AS [salesman] , net ) select client ,salesman ,[revenue] = SUM(net) from Clean group by client, salesman;
不能保證在執行時首先執行 CTE,然後執行聚合。優化器可能會重新排列這些位,但會選擇最佳性能。不過,它提供的內容可以保證實現您提供的查詢。這讓我們開發人員可以根據我們選擇的最佳人類理解來安排查詢,在這種情況下使用 CTE。(在某些特殊情況下,優化器給出的計劃效果不佳,最好的解決方案是重新安排 SQL;這不會是其中一種情況。)