数据透视/反透视计数

Posted

技术标签:

【中文标题】数据透视/反透视计数【英文标题】:Data Pivot / Unpivot Count 【发布时间】:2019-10-28 18:30:28 【问题描述】:

我需要一些关于 UnPivot/Pivot/Cross-Apply 类型操作的帮助。

背景:数据是每个数据库中每个表的行数,每天两次:早上和晚上。

样本数据:

CREATE TABLE [dbo].[DataCount](
    [DatabaseName] [varchar](255) NULL,
    [TableName] [varchar](255) NULL,
    [RowCount] [bigint] NULL,
    [Date] [date] NULL,
    [DateForAnalysis] [datetime] NULL,
    [Runtime] [varchar](50) NULL
) 



INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableA', 10, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 09:00:00.000' AS DateTime), N'Morning')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableB', 10, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 09:00:00.000' AS DateTime), N'Morning')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableC', 10, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 09:00:00.000' AS DateTime), N'Morning')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableA', 15, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 18:00:00.000' AS DateTime), N'Evening')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableB', 15, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 18:00:00.000' AS DateTime), N'Evening')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableB', 15, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 18:00:00.000' AS DateTime), N'Evening')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableA', 20, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 09:00:00.000' AS DateTime), N'Morning')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableB', 20, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 09:00:00.000' AS DateTime), N'Morning')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableC', 20, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 09:00:00.000' AS DateTime), N'Morning')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableA', 25, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 18:00:00.000' AS DateTime), N'Evening')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableB', 25, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 18:00:00.000' AS DateTime), N'Evening')
GO
INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) VALUES (N'DatabaseA', N'TableC', 25, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 18:00:00.000' AS DateTime), N'Evening')
GO 

所需的示例数据输出如下图所示 - 但欢迎就如何更好地呈现数据提出建议。

【问题讨论】:

你说你遇到了障碍;你在哪里卡住了?你能告诉我们你到目前为止的尝试吗?是否有您阅读过但不理解的具体问题?你在这里遇到的障碍是什么? 【参考方案1】:

你需要一个动态的支点。

DECLARE @ColNames NVARCHAR(MAX) = ''

SELECT @ColNames = @ColNames + ',' + DateAndRuntime
FROM (SELECT DISTINCT QUOTENAME( CONCAT([Date] , ' ',   [Runtime] )) DateAndRuntime FROM [dbo].[DataCount] ) T

SELECT @ColNames = STUFF( @ColNames ,1,1,'')

DECLARE @PilotSql NVARCHAR(MAX) = 'SELECT * FROM (
    SELECT [DatabaseName], [TableName], [RowCount], CONCAT([Date] , '' '', [Runtime] ) AS [DateAndRuntime] FROM [dbo].[DataCount] ) 
AS  SRC
PIVOT (SUM([RowCount]) FOR [DateAndRuntime] IN ('+@ColNames+')) PVT '

EXECUTE sp_executesql @PilotSql

结果:

DatabaseName   TableName       2019-10-01 Evening   2019-10-01 Morning   2019-10-02 Evening   2019-10-02 Morning
-------------- --------------- -------------------- -------------------- -------------------- --------------------
DatabaseA      TableA          15                   10                   25                   20
DatabaseA      TableB          30                   10                   25                   20
DatabaseA      TableC          NULL                 10                   25                   20

【讨论】:

【参考方案2】:

您可以使用单个值语句执行多行

INSERT [dbo].[DataCount] ([DatabaseName], [TableName], [RowCount], [Date], [DateForAnalysis], [Runtime]) 
   VALUES (N'DatabaseA', N'TableA', 10, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 09:00:00.000' AS DateTime), N'Morning'),
          (N'DatabaseA', N'TableB', 10, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 09:00:00.000' AS DateTime), N'Morning'),
          (N'DatabaseA', N'TableC', 10, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 09:00:00.000' AS DateTime), N'Morning'),
          (N'DatabaseA', N'TableA', 15, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 18:00:00.000' AS DateTime), N'Evening'),
          (N'DatabaseA', N'TableB', 15, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 18:00:00.000' AS DateTime), N'Evening'),
          (N'DatabaseA', N'TableB', 15, CAST(N'2019-10-01' AS Date), CAST(N'2019-10-01 18:00:00.000' AS DateTime), N'Evening'),
          (N'DatabaseA', N'TableA', 20, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 09:00:00.000' AS DateTime), N'Morning'),
          (N'DatabaseA', N'TableB', 20, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 09:00:00.000' AS DateTime), N'Morning'),
          (N'DatabaseA', N'TableC', 20, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 09:00:00.000' AS DateTime), N'Morning'),
          (N'DatabaseA', N'TableA', 25, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 18:00:00.000' AS DateTime), N'Evening'),
          (N'DatabaseA', N'TableB', 25, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 18:00:00.000' AS DateTime), N'Evening'),
          (N'DatabaseA', N'TableC', 25, CAST(N'2019-10-02' AS Date), CAST(N'2019-10-02 18:00:00.000' AS DateTime), N'Evening')
GO 

【讨论】:

以上是关于数据透视/反透视计数的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用数据透视和反透视的情况下在 SQL Server 中水平显示数据?

SQL 透视/反透视?

SQL 透视/反透视

数据透视表计数不正确

HIVE 数据透视和总和/计数

Pandas 数据透视表值计数