SQL Server:如何创建水平表

时间:2013-05-19 21:28:40

标签: sql sql-server

例如,如果我有下一个表:

| sensorid |date| value |
-------------------------
|    65000 | 00 |    32 |
|    65000 | 01 |    40 |
|    65000 | 02 |    35 |
|    65000 | 03 |    37 |
|    65000 | 04 |    39 |
|    65001 | 00 |    06 |
|    65001 | 01 |    10 |
|    65001 | 02 |    15 |
|    65001 | 03 |    26 |
|    65001 | 04 |    39 |

我想转换为此表?

| SENSORID | 00 | 01 | 02 | 03 | 04 |
------------------------------------
| 65000    | 32 | 40 | 35 | 37 | 39 |
| 65001    | 6  | 10 | 15 | 26 | 39 | 

是否有特殊方法或我必须找到一种方法来迭代一段时间?

我需要帮助。

3 个答案:

答案 0 :(得分:2)

可以做到,但你不会轻易获得动态查询。

正如您的问题的评论提示,使用您实际执行SQL的编程语言可能更容易实现。

如果您事先知道所有“类别”(在您的情况下为日期列),您可以创建这样的SQL:

select
    sensorid,
    max(case when date = 0 then value else 0 end) as date0,
    max(case when date = 1 then value else 1 end) as date1,
    max(case when date = 2 then value else 2 end) as date2,
    max(case when date = 3 then value else 3 end) as date3,
    max(case when date = 4 then value else 4 end) as date4
from
    yourtable
group by
    sensorid

以下是您可以试用的完整LINQPad脚本:

USE master
GO

IF EXISTS (SELECT * FROM sysdatabases WHERE name = 'SO16639641')
    DROP DATABASE SO16639641
GO

CREATE DATABASE SO16639641
GO

USE SO16639641
GO

CREATE TABLE original
(
    sensorid    int,
    date_       int,
    value       int
)
GO

INSERT INTO original
VALUES
    (65000, 00, 32),
    (65000, 01, 40),
    (65000, 02, 35),
    (65000, 03, 37),
    (65000, 04, 39),
    (65001, 00, 06),
    (65001, 01, 10),
    (65001, 02, 15),
    (65001, 03, 26),
    (65001, 04, 39)
GO

SELECT
    sensorid,
    MAX(CASE WHEN date_ = 0 THEN value ELSE 0 END) AS date0,
    MAX(CASE WHEN date_ = 1 THEN value ELSE 1 END) AS date1,
    MAX(CASE WHEN date_ = 2 THEN value ELSE 2 END) AS date2,
    MAX(CASE WHEN date_ = 3 THEN value ELSE 3 END) AS date3,
    MAX(CASE WHEN date_ = 4 THEN value ELSE 4 END) AS date4
FROM
    original
GROUP BY
    sensorid
GO

或下载here

我还添加了一个动态版本,它将根据数据确定要添加的日期列。更多涉及,但你可以在上面的链接找到两个脚本。

答案 1 :(得分:2)

PIVOT完全符合您的需要:

SELECT sensorid, 
       [00], [01], [02], [03], [04]
FROM MyTable
PIVOT
(
  MAX(value)
  FOR date IN ([00], [01], [02], [03], [04])
) AS PivotTable;

http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

答案 2 :(得分:0)

看起来您想要每天从每个传感器获取读数?您可以通过更改select语句来订购输出

,从而非常愉快地完成这项工作

从[tablename]按日期asc,sensorid asc选择日期,sensorid,值;

DATE SENSORID VALUE
00 65000 32
00 65001 06
01 65000 40
01 65001 10

如果它实际上需要水平格式化,我建议在MSDN上查看PIVOT