Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 透视多个字段?_Sql_Sql Server_Sql Server 2012_Pivot - Fatal编程技术网

Sql 透视多个字段?

Sql 透视多个字段?,sql,sql-server,sql-server-2012,pivot,Sql,Sql Server,Sql Server 2012,Pivot,我试图通过将两列分别放在第三列上来聚合它们(希望这是正确的术语)。我让它以一种方式工作,但它似乎笨重,所以我想知道是否有更好的方式。我发布了另外两种更具可读性但不起作用的方法 演示数据: DECLARE @counts TABLE ( machineID INT, workShift INT, goodCount INT, totalCount INT ); INSERT INTO @counts VALUES (1, 1, 5, 20), (1

我试图通过将两列分别放在第三列上来聚合它们(希望这是正确的术语)。我让它以一种方式工作,但它似乎笨重,所以我想知道是否有更好的方式。我发布了另外两种更具可读性但不起作用的方法

演示数据:

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
修复,但数字甚至不正确。我从这里得到了这个想法:

我能换些东西让2号或3号开始工作吗

有完全不同的方法更好吗


额外好处:如果要聚合的列比我的简单示例中的多,比如如果还有一个errorCounts列,该怎么办?或者,如果有两个以上的工作班次怎么办?我很好奇不同的解决方案是如何扩展的。

您可以跳过
pivot()
,像这样使用老式的pivot:

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
雷克斯测试仪:


您可以跳过
pivot()
,像这样使用旧式pivot:

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
雷克斯测试仪:


这是一个动态版本。如您所见,
交叉应用
将取消对数据的归档

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

这是一个动态版本。如您所见,
交叉应用
将取消对数据的归档

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

在重新阅读您的问题后,不清楚您想要的输出。。。聚合总计数还是不同的总计数?我在寻找每班期间每台机器的
goodCount
之和,以及每班期间每台机器的
totalCount
之和。我的解决方案底部的结果#1显示了我正在寻找的结果。在重新阅读您的问题后,返回到我的原始答案,不清楚您想要的输出。。。聚合总计数还是不同的总计数?我在寻找每班期间每台机器的
goodCount
之和,以及每班期间每台机器的
totalCount
之和。我的解决方案底部的结果#1显示了我正在寻找的结果。返回到我的原始答案当我用
@counts
替换
时,生成的SQL运行良好。但是,当我对动态SQL执行同样的操作时,我得到一个错误
必须声明表变量@counts
。发生了什么?@MarredCheese否。表变量在动态SQL中不可见,除非它们在动态SQL中定义。你可以使用临时表,它们是可见的。啊,好的。谢谢你的帮助!这是一个艰难的决定,但我选择SqlZim的答案仅仅是因为它是我实际要使用的(由于它的简单性)。然而,我真的很欣赏你的答案的可伸缩性,所以我对它投了更高的票。@MarredCheese条件聚合始终是我的第一选择。也就是说,我更喜欢动态的Pivot。(更易于动态构造)当我将
YourTable
替换为
@counts
时,生成的SQL非常有效。但是,当我对动态SQL执行同样的操作时,我得到一个错误
必须声明表变量@counts
。发生了什么?@MarredCheese否。表变量在动态SQL中不可见,除非它们在动态SQL中定义。你可以使用临时表,它们是可见的。啊,好的。谢谢你的帮助!这是一个艰难的决定,但我选择SqlZim的答案仅仅是因为它是我实际要使用的(由于它的简单性)。然而,我真的很欣赏你的答案的可伸缩性,所以我对它投了更高的票。@MarredCheese条件聚合始终是我的第一选择。也就是说,我更喜欢动态的Pivot。(更易于动态构造)