Simplify Dynamic SQL Pivot Table(简化动态 SQL 数据透视表)
问题描述
我根据以下内容编写了一个动态数据透视表查询.这是一个 SQL FIDDLE 供参考.
I have written a Dynamic Pivot Table Query based on the following. Here is a SQL FIDDLE for reference.
CREATE TABLE TestTable1 ([idnumber] INT, [DataTypeId] INT)
GO
INSERT INTO TestTable1
VALUES (1, 108), (1, 108), (1, 108), (2, 108),
(2, 108), (3, 108), (1, 109),(1, 109),
(1, 110),(2, 110),(1, 111),(4, 108),(4, 108),
(4, 110),(4, 111)
GO
这是我写的动态 SQL
Here is the Dynamic SQL that I wrote
DECLARE @SQL NVARCHAR(MAX),
@Cols NVARCHAR(MAX),
@ColsP NVARCHAR(MAX)
SELECT @Cols = STUFF((select ',
ISNULL([' + CAST([DataTypeId] as varchar(10)) + '], 0) AS ''' + CAST([DataTypeId] as varchar(10)) + ''''
FROM
(
SELECT [DataTypeId] FROM [TestTable1]
GROUP BY [DataTypeId]
HAVING [DataTypeId] <> ''
) AS d
ORDER BY [DataTypeId] FOR XML PATH(''),type).value('.','varchar(max)'),1,2,'')
-- /////////////THIS IS WHAT I WANT REMOVED ////////////////////
SELECT @ColsP = STUFF((select ',
[' + CAST([DataTypeId] as varchar(10)) + ']'
FROM
(
SELECT [DataTypeId] FROM [TestTable1]
GROUP BY [DataTypeId]
HAVING [DataTypeId] <> ''
) AS d
ORDER BY [DataTypeId] FOR XML PATH(''),type).value('.','varchar(max)'),1,2,'')
-- /////////////////////////////////////////////////////////////
SET @SQL = 'SELECT idnumber,' + @Cols + '
FROM
(SELECT idnumber, COUNT([DataTypeId]) AS Total, [DataTypeId] FROM [TestTable1]
GROUP BY idnumber, [DataTypeId]
HAVING [DataTypeId] <> ''''
) p
PIVOT
(
SUM(Total) FOR [DataTypeId] IN (' + @ColsP + ')
) AS pvt
ORDER BY pvt.idnumber'
-- print @SQL
EXECUTE( @SQL)
我得到了我想要的结果:
I get the result that I want:
| IDNUMBER | 108 | 109 | 110 | 111 |
|----------|-----|-----|-----|-----|
| 1 | 3 | 2 | 1 | 1 |
| 2 | 2 | 0 | 1 | 0 |
| 3 | 1 | 0 | 0 | 0 |
| 4 | 2 | 0 | 1 | 1 |
但我相信它可以做得更好.我想删除填充变量的位置 @ColsP
- SELECT @ColsP = STUFF((select...")
But I am sure it can be done better. I would like to remove where I populate the variable @ColsP
- SELECT @ColsP = STUFF((select...")
应该有一种方法可以让我通过 TestTable1
只需一个循环即可创建此动态代码.如您所见,我循环了两次.一次读取要为 select 语句创建的列,一次读取 PIVOT 表.
There should be a way where I can create this dynamic code with just one loop through TestTable1
. As you can see, I loop through it twice. Once to read what columns to create for the select statement, and once for the PIVOT table.
下面是动态 SQL 生成的代码:
Here is the code that is generated by the Dynamic SQL:
SELECT idnumber,
ISNULL([108], 0) AS '108',
ISNULL([109], 0) AS '109',
ISNULL([110], 0) AS '110',
ISNULL([111], 0) AS '111'
FROM
(
SELECT idnumber, COUNT([DataTypeId]) AS Total, [DataTypeId]
FROM [TestTable2]
GROUP BY idnumber, [DataTypeId]
HAVING [DataTypeId] <> ''
) p
PIVOT
(
SUM(Total) FOR [DataTypeId] IN ([108], [109], [110], [111])
) AS pvt
ORDER BY pvt.idnumber
推荐答案
您可以大大缩短您的代码.首先,您可以只使用 count
来聚合 PIVOT 中的数据.不需要内部计数来聚合数据或 HAVING
子句.最后,您只需要创建一次列列表.您可以轻松地将代码改进为:
You can shorten your code considerably. First, you can just use count
to aggregate the data in the PIVOT. There is no need for the inner count to aggregate the data or the HAVING
clause. Finally, you only need to create the list of columns once. You could easily improve the code to:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(DataTypeId)
from TestTable1
group by DataTypeId
order by DataTypeId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= N'SELECT idnumber, ' + @cols + N'
from
(
select idnumber, DataTypeId
from TestTable1
) x
pivot
(
count(DataTypeId)
for DataTypeId in (' + @cols + N')
) p '
exec sp_executesql @query;
请参阅 SQL Fiddle with Demo.这给出了相同的结果:
See SQL Fiddle with Demo. This gives the same result:
| IDNUMBER | 108 | 109 | 110 | 111 |
|----------|-----|-----|-----|-----|
| 1 | 3 | 2 | 1 | 1 |
| 2 | 2 | 0 | 1 | 0 |
| 3 | 1 | 0 | 0 | 0 |
| 4 | 2 | 0 | 1 | 1 |
这篇关于简化动态 SQL 数据透视表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:简化动态 SQL 数据透视表


- 如何将 Byte[] 插入 SQL Server VARBINARY 列 2021-01-01
- 更改自动增量起始编号? 2021-01-01
- 如何使用 pip 安装 Python MySQLdb 模块? 2021-01-01
- 在SQL中,如何为每个组选择前2行 2021-01-01
- 远程 mySQL 连接抛出“无法使用旧的不安全身份验证连接到 MySQL 4.1+"来自 XAMPP 的错误 2022-01-01
- 如何将 SonarQube 6.7 从 MySQL 迁移到 postgresql 2022-01-01
- 以一个值为轴心,但将一行上的数据按另一行分组? 2022-01-01
- SQL 临时表问题 2022-01-01
- 使用 Oracle PL/SQL developer 生成测试数据 2021-01-01
- 导入具有可变标题的 Excel 文件 2021-01-01