2017-01-17 6 views
0

私は3番目の列のそれぞれをピボットすることで2つの列を集計しようとしています(うまくいけば正しい用語です)。私はそれを一つの方法で動かすことができましたが、それはちょっとしたように思えるので、もっと良い方法があるのだろうかと思っています。私はもっ​​と読みやすいが、うまくいかない2つの方法を投稿した。複数のフィールドをピボットしますか?

デモデータ:

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

あなたの質問を再読み込みした後、希望する出力が不明です... aggregate totalCountまたはdistinct 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

ここでは、ダイナミックバージョンです。

enter image description here

生成:あなたはそれが可視化を支援する場合は、CROSS APPLYは以下を生成し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 

を見ることができるように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

'YourTable'を' @ counts'に置き換えると、生成されたSQLは完全に動作します。しかし、私が動的SQLに同じことをするとき、私はエラー 'テーブル変数@ counts'を宣言しなければなりません。何が起こっている? – MarredCheese

+0

@MarredCheese No.テーブル変数は、動的SQL内では定義されていない限り、動的SQLでは表示されません。テンポラリテーブルを使用することができます。 –

+0

ああ、大丈夫です。あなたのすべての協力に感謝します!それは厳しい呼び出しですが、私はSqlZimの答えを選んでいます。なぜなら、それは実際に私が使っているものだからです(そのシンプルさのせいで)。しかし、私はあなたの答えのスケーラビリティに本当に感謝しているので、私はそれをupvotingです。 – MarredCheese

関連する問題