透视sql server表

时间:2016-06-08 09:07:24

标签: sql-server sql-server-2008 pivot

如何使用SQL查询将SQL Server表meterdata转换为Result_Table

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     

Result_Table

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)。我正在尝试以下查询,但没有得到结果。有人可以编辑查询,以便输出为Results_Table,如上所述。最好还是请使用数据透视查询。查询是

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

2 个答案:

答案 0 :(得分:0)

以下是您可以尝试的不使用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

答案 1 :(得分:0)

动态SQL将帮助您(我使用##MeterDatatempdb您必须使用您的实际表和数据库名称)。将与源表中的任意数量的列一起使用。几条评论:

  • 您需要将CASTCONVERT所有列添加到一种类型(我在nvarchar(10)变量中使用@p);
  • 我排除了meternodatetimeblock列,因为您的数据集中没有用作参数;
  • 您可以在执行前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