Sql server 透视sql server表
如何使用SQL查询将SQL Server表Sql server 透视sql server表,sql-server,sql-server-2008,pivot,Sql Server,Sql Server 2008,Pivot,如何使用SQL查询将SQL Server表meterdata转换为Result\u表 MeterData表存储功率和频率,并具有主键(meterno,date,timeblock),meterno列具有可变的值编号 MeterData表格: meterno date timeblock power frequency -------------------------------------------------- 89 1-Apr-16 1
meterdata
转换为Result\u表
MeterData
表存储功率和频率,并具有主键(meterno,date,timeblock)
,meterno列具有可变的值编号
MeterData表格:
meterno date timeblock power frequency
--------------------------------------------------
89 1-Apr-16 1 500 50.02
89 1-Apr-16 2 100 49.99
90 1-Apr-16 1 200 50.02
90 1-Apr-16 2 300 49.89
结果表
date timeblock 89_power 90_power 89_frequency 90_frequency
1-Apr-16 1 500 200 50.02 50.02
1-Apr-16 2 100 300 49.99 49.89
为了简单起见,让我们假设meterno列具有固定数量的值,例如(89,90)。我正在尝试以下查询,但没有得到结果。是否有人可以编辑查询结果,以便输出如上所示的结果表。最好使用pivot query进行回答。问题是
SELECT
*
FROM
(
SELECT
*
FROM meterdata
) AS P
PIVOT
(
sum (power ) FOR meterno IN (89, 90)
) AS pv1
PIVOT
(
sum (frequency ) FOR meterno IN (89, 90)
) AS pv2
GO
以下是一个pivot查询,您可以尝试它不使用SQL Server
pivot
操作:
SELECT date, timeblock
SUM(CASE WHEN meterno=89 THEN power ELSE 0 END) AS meterno-89_power,
SUM(CASE WHEN meterno=90 THEN power ELSE 0 END) AS meterno-90_power,
SUM(CASE WHEN meterno=89 THEN frequency ELSE 0 END) AS meterno-89_frequency,
SUM(CASE WHEN meterno=90 THEN frequency ELSE 0 END) AS meterno-89_frequency
FROM MeterData
GROUP BY date, timeblock
以下是一个pivot查询,您可以尝试它不使用SQL Server
pivot
操作:
SELECT date, timeblock
SUM(CASE WHEN meterno=89 THEN power ELSE 0 END) AS meterno-89_power,
SUM(CASE WHEN meterno=90 THEN power ELSE 0 END) AS meterno-90_power,
SUM(CASE WHEN meterno=89 THEN frequency ELSE 0 END) AS meterno-89_frequency,
SUM(CASE WHEN meterno=90 THEN frequency ELSE 0 END) AS meterno-89_frequency
FROM MeterData
GROUP BY date, timeblock
动态SQL将帮助您(我使用了##MeterData
和tempdb
您必须使用实际的表和数据库名称)。将处理源表中任意数量的列。几点意见:
- 您需要将所有列转换为一种类型(我在
变量中使用了@p
)李>nvarchar(10)
- 我排除了列
,meterno
,date
,因为数据集中没有用作参数李>timeblock
- 您可以在执行之前
,查看要执行的格式PRINT@sql
DECLARE @p nvarchar(max), @c nvarchar(max), @s nvarchar(max), @sql nvarchar(max)
--That will get you this:
--,CAST([power] as nvarchar(10)) [power],CAST([frequency] as nvarchar(10)) [frequency]
SELECT @p = (
SELECT ',CAST(' + QUOTENAME(COLUMN_NAME) + ' as nvarchar(10)) '+ QUOTENAME(COLUMN_NAME)
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'##MeterData' AND COLUMN_NAME NOT IN ('meterno','date','timeblock')
FOR XML PATH('')
)
--[power],[frequency]
SELECT @c = STUFF((
SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'##MeterData' AND COLUMN_NAME NOT IN ('meterno','date','timeblock')
FOR XML PATH('')),1,1,'')
--[frequency89],[frequency90],[power89],[power90]
SELECT @s = STUFF((
SELECT DISTINCT ','+QUOTENAME(COLUMN_NAME + CAST(meterno as nvarchar(10)))
FROM ##MeterData m
CROSS JOIN (
SELECT COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'##MeterData' AND COLUMN_NAME NOT IN ('meterno','date','timeblock')
) as p
FOR XML PATH('')),1,1,'')
--Put it all in dynamic query
SELECT @sql = '
SELECT *
FROM (
SELECT [date],
timeblock,
params + CAST(meterno as nvarchar(10)) as params,
[values]
FROM (
SELECT meterno,
[date],
timeblock'
+@p+
'
FROM ##MeterData
) as p
UNPIVOT (
[values] FOR params IN ('+@c+')
) as unpvt
) as p2
PIVOT (
MAX([Values]) FOR params IN ('+@s+')
) as pvt'
--And execute
EXEC sp_executesql @sql
输出:
date timeblock frequency89 frequency90 power89 power90
2016-04-01 1 50.02 50.02 500 200
2016-04-01 2 49.99 49.89 100 300
动态SQL将帮助您(我使用了##MeterData
和tempdb
您必须使用实际的表和数据库名称)。将处理源表中任意数量的列。几点意见:
- 您需要将所有列转换为一种类型(我在
变量中使用了@p
)李>nvarchar(10)
- 我排除了列
,meterno
,date
,因为数据集中没有用作参数李>timeblock
- 您可以在执行之前
,查看要执行的格式PRINT@sql
DECLARE @p nvarchar(max), @c nvarchar(max), @s nvarchar(max), @sql nvarchar(max)
--That will get you this:
--,CAST([power] as nvarchar(10)) [power],CAST([frequency] as nvarchar(10)) [frequency]
SELECT @p = (
SELECT ',CAST(' + QUOTENAME(COLUMN_NAME) + ' as nvarchar(10)) '+ QUOTENAME(COLUMN_NAME)
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'##MeterData' AND COLUMN_NAME NOT IN ('meterno','date','timeblock')
FOR XML PATH('')
)
--[power],[frequency]
SELECT @c = STUFF((
SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'##MeterData' AND COLUMN_NAME NOT IN ('meterno','date','timeblock')
FOR XML PATH('')),1,1,'')
--[frequency89],[frequency90],[power89],[power90]
SELECT @s = STUFF((
SELECT DISTINCT ','+QUOTENAME(COLUMN_NAME + CAST(meterno as nvarchar(10)))
FROM ##MeterData m
CROSS JOIN (
SELECT COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'##MeterData' AND COLUMN_NAME NOT IN ('meterno','date','timeblock')
) as p
FOR XML PATH('')),1,1,'')
--Put it all in dynamic query
SELECT @sql = '
SELECT *
FROM (
SELECT [date],
timeblock,
params + CAST(meterno as nvarchar(10)) as params,
[values]
FROM (
SELECT meterno,
[date],
timeblock'
+@p+
'
FROM ##MeterData
) as p
UNPIVOT (
[values] FOR params IN ('+@c+')
) as unpvt
) as p2
PIVOT (
MAX([Values]) FOR params IN ('+@s+')
) as pvt'
--And execute
EXEC sp_executesql @sql
输出:
date timeblock frequency89 frequency90 power89 power90
2016-04-01 1 50.02 50.02 500 200
2016-04-01 2 49.99 49.89 100 300
谢谢蒂姆早日回复。但我之前没有提到meterno列是可变的,即它可以没有任何值,如89、90、91、95……如果
meterno
只有一组固定的值,那么只需通过添加额外的CASE
语句来相应地修改我的查询。如果列数很大或可变,则需要使用动态SQL来处理。它不是很大,而是可变的。在这种情况下,如何使用动态SQL?i、 我想要现成的查询!您可以尝试搜索此解决方案的堆栈溢出,它已被回答了很多次。感谢Tim的早期答复。但我之前没有提到meterno列是可变的,即它可以没有任何值,如89、90、91、95……如果meterno
只有一组固定的值,那么只需通过添加额外的CASE
语句来相应地修改我的查询。如果列数很大或可变,则需要使用动态SQL来处理。它不是很大,而是可变的。在这种情况下,如何使用动态SQL?i、 我想要现成的查询!您可以尝试搜索此解决方案的堆栈溢出,它以前已被回答过多次。感谢@gofr1给出的精彩回答。在过去的两天里,我一直在努力完成这个任务,而你在几分钟内就解决了。谢谢@gofr1,给了我一个精彩的回答。在过去的两天里,我一直在努力完成这个任务,而你在几分钟内就解决了这个问题。