方案
XYZ公司销售产品。公司通过检查完成整个订单所需的时间来衡量其绩效。每个订单都经历多个状态(例如:打开,待定,关闭)
他们会计算每个状态的天数,以了解订单在特定状态下的天数。日期以两种不同的方式计算,即工作日和日历天
请参阅下表:
问题
如何将此表转换为下图所示的数据透视表?还有如何添加到每个工作日和工作日状态总计的其他列。
期望的结果:
答案 0 :(得分:1)
你可以这样做:
SELECT *
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
) AS t
PIVOT
(
MAX(DayCount)
For StatusType IN(OpenWorking,
OpenCalendar,
CloseWorking,
CloseCalendar,
PendingWorking,
PendingCalendar,
TotalWorking,
TotalCalendar)
) AS p;
这会给你:
如果您不想手动记下所有状态,那么您可以动态地执行:
DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);
SELECT @cols = STUFF((SELECT distinct ',' +
QUOTENAME(StatusType)
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT @query = 'SELECT *
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = ''Working'' THEN ''TotalWorking'' ELSE ''TotalCalendar'' END,
DayCount
FROM CalendarTable
) AS t
PIVOT
(
MAX(DayCount)
For StatusType IN(' + @cols + ')' +
') p';
execute(@query);
<强>更新强>
对于列名,您可以创建一个新变量@colnames
并使用您想要的名称填充它。对于Totals,您可以添加WHERE
子句以使状态的总数仅为活动和待处理状态。所以你的查询将是这样的:
DECLARE @cols AS NVARCHAR(MAX);
DECLARE @colnames AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);
SELECT @cols = STUFF((SELECT distinct ',' +
QUOTENAME(StatusType)
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
WHERE OrderStatus IN('Active', 'Pending')
) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT @colnames = STUFF((SELECT distinct ',' +
QUOTENAME(StatusType) + ' AS ' + QUOTENAME(StatusTypeName)
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount,
OrderStatus + CASE WHEN CountType = 'Working' THEN 'WorkDays' ELSE 'CalDays' END AS StatusTypeName
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END
FROM CalendarTable
WHERE OrderStatus IN('Active', 'Pending')
) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT @query = 'SELECT OrderID , ' + @colnames + '
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = ''Working'' THEN ''TotalWorking'' ELSE ''TotalCalendar'' END,
DayCount
FROM CalendarTable
WHERE OrderStatus IN(''Active'', ''Pending'')
) AS t
PIVOT
(
SUM(DayCount)
For StatusType IN(' + @cols + ')' +
') p';
execute(@query);
这会给你:
如果要在手动数据透视查询中添加where子句,可以执行以下操作:
SELECT *
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
WHERE ...
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
WHERE ...
) AS t
PIVOT
(
MAX(DayCount)
For StatusType IN(OpenWorking,
OpenCalendar,
CloseWorking,
CloseCalendar,
PendingWorking,
PendingCalendar,
TotalWorking,
TotalCalendar)
) AS p;