取消透视多列并分组为新列

Unpivot multiple columns and group into new columns

我正在处理一个客户数据,它有多个参数,例如列中每个月的预计单位、预计值、数量单位、数量值、Parm 单位、Parm 值。

每个参数都带有月份名称前缀,例如 JAN_Projected 单位、JAN_ 预计值、JAN_Quantity 单位、JAN_ 数量值、JAN_ Parm 单位、JAN_ Parm 值。

这是我的 table 的架构:

CREATE TABLE [dbo].[tbl_forum_data](
    [Sno] [float] NULL,
    [JAN_Projected units] [float] NULL,
    [JAN_Projected value] [float] NULL,
    [JAN_Quantity units] [float] NULL,
    [JAN_Quantity value] [float] NULL,
    [JAN_Parm Units  ] [float] NULL,
    [JAN_Parm Value  ] [float] NULL,
    [FEB_Projected units] [float] NULL,
    [FEB_Projected value] [float] NULL,
    [FEB_Quantity units] [float] NULL,
    [FEB_Quantity value] [float] NULL,
    [FEB_Parm Units  ] [float] NULL,
    [FEB_Parm Value  ] [float] NULL,
    [MAR_Projected units] [float] NULL,
    [MAR_Projected value] [float] NULL,
    [MAR_Quantity units] [float] NULL,
    [MAR_Quantity value] [float] NULL,
    [MAR_Parm Units  ] [float] NULL,
    [MAR_Parm Value  ] [float] NULL
) ON [PRIMARY]

我想根据每个月对每个预计单位、预计值、数量单位、数量值、参数单位和参数值进行分组,如下面的屏幕截图

如果那不可能,至少我想将列更改为行并将单位分组为单独的列,将值分组为单独的列,如下所示。

我尝试进行交叉连接,但我能够将值放入行中。下面是我使用的代码:

select Sno
       ,G.EventName
       ,G.EventDate
from [db_Temp].[dbo].[tbl_forum_data] as T
  cross apply (values ([JAN_Projected units], 'JAN_Projected units'),
([JAN_ Projected value], 'JAN_ Projected value'),
([JAN_Quantity units], 'JAN_Quantity units'),
([JAN_ Quantity value], 'JAN_ Quantity value'),
([JAN_ Parm Units  ], 'JAN_ Parm Units'),
([JAN_ Parm Value  ], 'JAN_ Parm Value'),
([FEB_ Projected units], 'FEB_ Projected units'),
([FEB_ Projected value], 'FEB_ Projected value'),
([FEB_Quantity units], 'FEB_Quantity units'),
([FEB_ Quantity value], 'FEB_ Quantity value'),
([FEB_ Parm Units  ], 'FEB_ Parm Units'),
([FEB_ Parm Value  ], 'FEB_ Parm Value'),
([MAR_ Projected units], 'MAR_ Projected units'),
([MAR_ Projected value], 'MAR_ Projected value'),
([MAR_ Quantity units], 'MAR_ Quantity units'),
([MAR_ Quantity value], 'MAR_ Quantity value'),
([MAR_ Parm Units  ], 'MAR_ Parm Units'),
([MAR_ Parm Value  ], 'MAR_ Parm Value')) as G(EventDate, EventName);

非常感谢任何帮助。 Link 为提琴手 SQL Schema

此脚本显示了执行此操作的两种方法。

  1. 使用 CROSS APPLY 生成具有所需列的行
  2. 使用 UNPIVOT + 枢轴使用 MAX(CASE ...)
CREATE TABLE #tbl_forum_data(
    [Sno] [float] NULL,
    [JAN_Projected units] [float] NULL, [JAN_Projected value] [float] NULL,[JAN_Quantity units] [float] NULL,
    [JAN_Quantity value] [float] NULL, [JAN_Parm Units  ] [float] NULL,[JAN_Parm Value  ] [float] NULL,
    [FEB_Projected units] [float] NULL, [FEB_Projected value] [float] NULL, [FEB_Quantity units] [float] NULL,
    [FEB_Quantity value] [float] NULL, [FEB_Parm Units  ] [float] NULL, [FEB_Parm Value  ] [float] NULL,
    [MAR_Projected units] [float] NULL, [MAR_Projected value] [float] NULL, [MAR_Quantity units] [float] NULL,
    [MAR_Quantity value] [float] NULL, [MAR_Parm Units  ] [float] NULL, [MAR_Parm Value  ] [float] NULL
);
INSERT INTO #tbl_forum_data([Sno],
    [JAN_Projected units],[JAN_Projected value],[JAN_Quantity units],[JAN_Quantity value],[JAN_Parm Units  ],[JAN_Parm Value  ],
    [FEB_Projected units],[FEB_Projected value],[FEB_Quantity units],[FEB_Quantity value],[FEB_Parm Units  ],[FEB_Parm Value  ],
    [MAR_Projected units],[MAR_Projected value],[MAR_Quantity units],[MAR_Quantity value],[MAR_Parm Units  ],[MAR_Parm Value  ]
)
VALUES(1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18);

-- using cross apply/union all
SELECT
    Sno,[Month],[Projected units],[Projected value],[Quantity units],[Quantity value],[Parm Units],[Parm Value]
FROM
    #tbl_forum_data
    CROSS APPLY (
        SELECT 'JAN' AS [Month], 0 AS [MonthSort],
               [JAN_Projected units] AS [Projected units], [JAN_Projected value] AS [Projected value],
               [JAN_Quantity units]  AS [Quantity units] , [JAN_Quantity value]  AS [Quantity value] ,
               [JAN_Parm Units  ]    AS [Parm Units]     , [JAN_Parm Value  ]    AS [Parm Value]
        UNION ALL
        SELECT 'FEB' AS [Month], 1 AS [MonthSort],
               [FEB_Projected units] AS [Projected units], [FEB_Projected value] AS [Projected value],
               [FEB_Quantity units]  AS [Quantity units] , [FEB_Quantity value]  AS [Quantity value] ,
               [FEB_Parm Units  ]    AS [Parm Units]     , [FEB_Parm Value  ]    AS [Parm Value]
        UNION ALL
        SELECT 'MAR' AS [Month], 2 AS [MonthSort],
               [MAR_Projected units] AS [Projected units], [MAR_Projected value] AS [Projected value],
               [MAR_Quantity units]  AS [Quantity units] , [MAR_Quantity value]  AS [Quantity value] ,
               [MAR_Parm Units  ]    AS [Parm Units]     , [MAR_Parm Value  ]    AS [Parm Value]
    ) AS up
ORDER BY
    Sno,[MonthSort];

-- using unpivot / pivot (using MAX(CASE ...) for multi column pivot)
SELECT
    Sno,[Month],
    [Projected units]=MAX(CASE WHEN category='Projected units' THEN value END),
    [Projected value]=MAX(CASE WHEN category='Projected value' THEN value END),
    [Quantity units]=MAX(CASE WHEN category='Quantity units' THEN value END),
    [Quantity value]=MAX(CASE WHEN category='Quantity value' THEN value END),
    [Parm Units]=MAX(CASE WHEN category='Parm Units  ' THEN value END),
    [Parm Value]=MAX(CASE WHEN category='Parm Value  ' THEN value END)
FROM
    (
        SELECT
            Sno,[Month]=LEFT(DataPoint,3),category=SUBSTRING(DataPoint,5,LEN(DataPoint)),value
        FROM
            #tbl_forum_data
            UNPIVOT (
                value FOR DataPoint IN (
                    [JAN_Projected units],[JAN_Quantity units],[JAN_Parm Units  ],
                    [FEB_Projected units],[FEB_Quantity units],[FEB_Parm Units  ],
                    [MAR_Projected units],[MAR_Quantity units],[MAR_Parm Units  ]
                )
            ) AS up_units
        UNION ALL
        SELECT
            Sno,[Month]=LEFT(DataPoint,3),category=SUBSTRING(DataPoint,5,LEN(DataPoint)),value
        FROM
            #tbl_forum_data
            UNPIVOT (
                value FOR DataPoint IN (
                    [JAN_Projected value],[JAN_Quantity value],[JAN_Parm value  ],
                    [FEB_Projected value],[FEB_Quantity value],[FEB_Parm value  ],
                    [MAR_Projected value],[MAR_Quantity value],[MAR_Parm value  ]
                )
            ) AS up_units
    ) AS up
GROUP BY
    Sno,[Month]
ORDER BY
    Sno,CASE [Month] WHEN 'JAN' THEN 0 WHEN 'FEB' THEN 1 ELSE 2 END;

DROP TABLE #tbl_forum_data;

1 和 2 的结果:

+-----+-------+-----------------+-----------------+----------------+----------------+------------+------------+
| Sno | Month | Projected units | Projected value | Quantity units | Quantity value | Parm Units | Parm Value |
+-----+-------+-----------------+-----------------+----------------+----------------+------------+------------+
|   1 | JAN   |               1 |               2 |              3 |              4 |          5 |          6 |
|   1 | FEB   |               7 |               8 |              9 |             10 |         11 |         12 |
|   1 | MAR   |              13 |              14 |             15 |             16 |         17 |         18 |
+-----+-------+-----------------+-----------------+----------------+----------------+------------+------------+