T-SQL数据透视表

时间:2017-01-31 18:06:50

标签: sql-server tsql pivot

我有一个表MachineStatus,用于存储机器的状态历史记录。 该表如下所示:

| MachineStatusId                        |   From              |   To                |   State |   MachineId                           |
----------------------------------------------------------------------------------------------------------------------------------------
|   B065FC43-DBE7-E611-9BDB-801F02F47041 | 2017-01-30 07:00:00 | 2017-01-30 08:00:00 |       1 | 92649C7B-E962-4EB1-B631-00086EECA98A  |
|   B165FC43-DBE7-E611-9BDB-801F02F47041 | 2017-01-30 08:00:00 | 2017-01-30 09:00:00 |     200 | 92649C7B-E962-4EB1-B631-00086EECA98A  |
|   B265FC43-DBE7-E611-9BDB-801F02F47041 | 2017-01-30 07:00:00 | 2017-01-30 08:00:00 |       1 | A2649C7B-E962-4EB1-B631-00086EECA98A  |
|   B365FC43-DBE7-E611-9BDB-801F02F47041 | 2017-01-30 08:00:00 | 2017-01-30 09:00:00 |     500 | A2649C7B-E962-4EB1-B631-00086EECA98A  |

为每台计算机存储每个状态更改的记录,当某个[From]有效时,[To]时会显示信息[State]。 我想计算每台机器在每个州花费的时间。

结果应如下所示:

| MachineId                              |   Alias         |   State1 |   State200 |   State500 |
-------------------------------------------------------------------------------------------------
|   92649C7B-E962-4EB1-B631-00086EECA98A | Somename        |       60 |         60 |          0 |
|   A2649C7B-E962-4EB1-B631-00086EECA98A | Some other name |       60 |          0 |         60 |

每个州都应该表示为一个列。

到目前为止,我已经尝试过这个:

SELECT
    MAX(mState.MachineId),
    MAX(m.Alias),
    SUM(CASE mState.State WHEN 1 THEN mState.Diff ELSE 0 END) AS CritTime,
    SUM(CASE mState.State WHEN 200 THEN mState.Diff ELSE 0 END) AS OpTime,
    SUM(CASE mState.State WHEN 500 THEN mState.Diff ELSE 0 END) AS OtherTime
FROM 
    (
        SELECT
            DATEDIFF(MINUTE, ms.[From], ISNULL(ms.[To], GETDATE())) AS Diff,
            ms.State AS State,
            MachineId
        FROM
            MachineStatus ms
        WHERE
            ms.[From] >= @rangeFrom AND
            (ms.[To] <= @rangeEnd OR ms.[To] IS NULL)
    ) as mState

    INNER JOIN Machines m ON m.MachineId = mState.MachineId
GROUP BY
    mState.MachineId,
    m.Alias,
    mState.State

计算时间并按机器分组结果但我无法弄清楚如何减少结果集每个机器只包含一行但每个状态有一列。

1 个答案:

答案 0 :(得分:3)

我开始使用您的子查询而不对您的计算数据应用任何总和:

    SELECT m.MachineId,
           m.Alias,
           Minutes,
           s.State
    FROM machines m
         INNER JOIN states s ON m.MachineId = s.MachineId

然后您可以pivot() [State]并计算此表单中每个州的sum()

WITH Calc AS
(
    SELECT m.MachineId,
           m.Alias,
           Minutes,
           s.State
    FROM machines m
         INNER JOIN states s ON m.MachineId = s.MachineId
)
SELECT MachineId, Alias, [State1], [State2], [State500]
FROM
(SELECT MachineId, Alias, State, Minutes FROM Calc) AS SourceTable
PIVOT
(
    SUM(Minutes) FOR State IN ([State1],[State2],[State500])
) AS PivotTable;

结果如下:

+--------------------------------------+---------+--------+--------+----------+
|               MachineId              |  Alias  | State1 | State2 | State500 |
+--------------------------------------+---------+--------+--------+----------+
| 92649C7B-E962-4EB1-B631-00086EECA98A | Alias 1 | 100    | 100    | 100      |
+--------------------------------------+---------+--------+--------+----------+
| A2649C7B-E962-4EB1-B631-00086EECA98A | Alias 2 | 10     | 20     | 70       |
+--------------------------------------+---------+--------+--------+----------+

请注意,您必须知道有多少状态会返回您的数据。

可在此处查看:http://rextester.com/DHDX77489