2017-01-17 52 views
0

我想通過在第三列上旋轉它們來合計兩列(希望這是正確的術語)。我以某種方式工作,但看起來笨重,所以我想知道是否有更好的方法。我發佈了另外兩種更具可讀性但不起作用的方式。樞軸多個字段?

演示數據:

DECLARE @counts TABLE (
    machineID INT, 
    workShift INT, 
    goodCount INT, 
    totalCount INT 
); 

INSERT INTO @counts 
VALUES 
    (1, 1, 5, 20), 
    (1, 1, 5, 20), 
    (1, 2, 10, 20), 
    (1, 2, 10, 20), 
    (1, 2, 10, 20), 
    (2, 1, 50, 200), 
    (2, 1, 50, 200), 
    (2, 2, 100, 200), 
    (2, 2, 100, 200), 
    (2, 2, 100, 200); 

SELECT * 
FROM @counts 
ORDER BY machineID, workShift; 

result: 
machineID workShift goodCount totalCount 
1   1   5   20 
1   1   5   20 
1   2   10   20 
1   2   10   20 
1   2   10   20 
2   1   50   200 
2   1   50   200 
2   2   100   200 
2   2   100   200 
2   2   100   200 

#1這工作,但讓我覺得我過於複雜的事情:

WITH goodTable AS (
    SELECT machineID, [1] AS g1, [2] AS g2 
    FROM (SELECT machineID, goodCount, workShift FROM @counts) AS t 
    PIVOT (SUM(goodCount) FOR workShift IN ([1], [2])) AS piv 
    ), 
totalTable AS (
    SELECT machineID, [1] AS t1, [2] AS t2 
    FROM (SELECT machineID, totalCount, workShift FROM @counts) AS t 
    PIVOT (SUM(totalCount) FOR workShift IN ([1], [2])) AS piv 
    ) 
SELECT g.machineID, g1, t1, g2, t2 
FROM goodTable as g 
JOIN totalTable as t ON g.machineID = t.machineID 
ORDER BY machineID; 

result: 
machineID g1  t1  g2  t2 
1   10  40  30  60 
2   100  400  300  600 

#2我會愛能夠做這樣的事情,因爲它很可讀,但不會編譯。

SELECT 
    machineID, 
    g.[1] AS g1, 
    t.[1] AS t1, 
    g.[2] AS g2, 
    t.[2] AS t2 
FROM @counts 
PIVOT (SUM(goodCount) FOR workShift IN ([1], [2])) AS g 
PIVOT (SUM(totalCount) FOR workShift IN ([1], [2])) AS t 
ORDER BY machineID; 

result: 
The multi-part identifier "g.1" could not be bound. 
The multi-part identifier "g.2" could not be bound. 

#3這是應該工作,但沒有一個解決辦法。它產生的額外行可以通過GROUP BY修復,除了數字甚至不正確。我有這個想法從這裏:https://social.msdn.microsoft.com/Forums/sqlserver/en-US/7db49578-a1ef-4e53-864b-c61c5e1150f7/how-do-i-aggregate-on-more-than-one-column-within-a-pivot?forum=transactsql

WITH countsPivotable AS (
    SELECT machineID, goodCount, totalCount, 
    workshift AS ws1, 
    workshift + 10 AS ws2 
    FROM @counts) 
SELECT 
    machineID, 
    [1] AS g1, 
    [11] AS t1, 
    [2] AS g2, 
    [12] AS t2 
FROM countsPivotable 
PIVOT (SUM(goodCount) FOR ws1 IN ([1], [2])) AS piv 
PIVOT (SUM(totalCount) FOR ws2 IN ([11], [12])) AS piv 
ORDER BY machineID; 

result: 
machineID g1  t1  g2  t2 
1   NULL NULL 30  20 
1   10  20  NULL NULL 
2   NULL NULL 300  200 
2   100  200  NULL NULL 

我可以改變一些事來報復#2或#3工作?

是否有完全不同的方法更好?

獎勵:如果在我的簡單示例中有更多的聚合列會發生什麼情況,比如還有一個errorCounts列?或者如果有超過2個工作班次?我很好奇不同解決方案的規模。

+0

重新閱讀您的問題後,目前還不清楚您的期望輸出...總計totalCount或不同totalCount? –

+0

我正在爲每臺機器在每次班次期間的'goodCount'總數以及每次班次期間每臺機器的'totalCount'總和。我的解決方案#1底部的結果顯示了我正在尋找的內容。 – MarredCheese

+0

恢復爲我原來的答案 –

回答

2

你可以跳過pivot()並使用舊風格支點是這樣的:

rextester:http://rextester.com/HXUE97581

select 
    MachineId 
    , Good_1 = sum(case when workshift = 1 then goodcount else 0 end) 
    , Total_1 = sum(case when workshift = 1 then totalcount else 0 end) 
    , Good_2 = sum(case when workshift = 2 then goodcount else 0 end) 
    , Total_2 = sum(case when workshift = 2 then totalcount else 0 end) 
    from @counts 
    group by MachineId 
1

這裏是一個動態版本。正如你所看到的Cross Apply將逆轉置數據

Declare @SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(concat('g',[workShift]))+',' + QuoteName(concat('t',[workShift])) From Yourtable Order by 1 For XML Path('')),1,1,'') 
Select @SQL = ' 
Select [machineID],' + @SQL + ' 
From (
     Select A.machineID 
       ,B.* 
     From YourTable A 
     Cross Apply (
        Values (concat(''g'',A.workShift),A.goodCount) 
          ,(concat(''t'',A.workShift),A.totalCount) 
       ) B (Item,Value) 
    ) A 
Pivot (sum(Value) For [Item] in (' + @SQL + ')) p' 
Exec(@SQL); 

返回

machineID g1 t1 g2 t2 
1   10 40 30 60 
2   100 400 300 600 

如果它與可視化幫助,在CROSS APPLY生成以下內容:

enter image description here

和生成的SQL看起來像這樣:

Select [machineID],[g1],[t1],[g2],[t2] 
From (
     Select A.machineID 
       ,B.* 
     From YourTable A 
     Cross Apply (
        Values (concat('g',A.workShift),A.goodCount) 
          ,(concat('t',A.workShift),A.totalCount) 
       ) B (Item,Value) 
    ) A 
Pivot (sum(Value) For [Item] in ([g1],[t1],[g2],[t2])) p 
+0

當我用@ counts替換YourTable時,生成的SQL完美工作。但是,當我對動態SQL執行相同操作時,出現錯誤「必須聲明表變量@ counts」。發生什麼事? – MarredCheese

+0

@MarredCheese否表格變量在Dynamic SQL中不可見,除非它們是在動態SQL中定義的。你可以使用臨時表,它們是可見的。 –

+0

啊,好的。感謝你的幫助!這是一個棘手的電話,但我選擇SqlZim的答案只是因爲它是我實際上要使用的(由於其簡單)。不過,我真的很感謝你的答案的可擴展性,所以我正在對它進行評估。 – MarredCheese