Pergunta

I have a table with hourly statistics that I need to pivot (or unpivot?)

The starting table is of the form:

[SystemID] [Hour] [CallStarts] [AvgDuration]  
    1         0        3           27
    1         1       10           58
    1         2       43           45
    1         3       54           63
    2         0        6           56
    2         1       46           98
    2         2       56           67
    2         3       65           77  

And I need the output to be:

[SystemID] [Statistic] [Hr0] [Hr1] [Hr2] [Hr3]  
     1     CallStarts    3    10     43    54  
     1     AvgDuration  27    58     45    63
     2     CallStarts    6    46     56    65
     2     AvgDuration  56    98     67    77  

I'm using SQL Server 2008R2. I understand the basics of pivot tables but I don't have much experience with them. Its the [Statistic] column that has me for a loss.

Foi útil?

Solução

Here is a way to get these results without pivot, depending on indexes and data size it may be faster:

SELECT SystemID, 
       MAX('CallStarts') AS Statistic, 
       SUM(CASE WHEN Hour = 0 THEN CallStarts ELSE 0 END) AS Hr0,
       SUM(CASE WHEN Hour = 1 THEN CallStarts ELSE 0 END) AS Hr1,
       SUM(CASE WHEN Hour = 2 THEN CallStarts ELSE 0 END) AS Hr2,
       SUM(CASE WHEN Hour = 3 THEN CallStarts ELSE 0 END) AS Hr3
FROM Table
GROUP BY SystemID
  UNION ALL
SELECT SystemID, 
       MAX('AvgDuration') AS Statistic, 
       SUM(CASE WHEN Hour = 0 THEN AvgDuration ELSE 0 END) AS Hr0,
       SUM(CASE WHEN Hour = 1 THEN AvgDuration ELSE 0 END) AS Hr1,
       SUM(CASE WHEN Hour = 2 THEN AvgDuration ELSE 0 END) AS Hr2,
       SUM(CASE WHEN Hour = 3 THEN AvgDuration ELSE 0 END) AS Hr3
FROM Table
GROUP BY SystemID
ORDER BY SystemID, Statistic ASC

Outras dicas

You can query each type of the statistics alone, and then have them unioned. I used the same schema built by @attila on SQL Fiddle.

WITH callS AS (SELECT systemid, hour, callstarts FROM t),
callD AS (SELECT systemid, hour, avgduration FROM t)

SELECT systemid, 'callStarts' AS [statistics], [0] as Hr0, [1] as Hr1, [2] as Hr2, [3] AS Hr3
FROM callS pivot (max(callStarts) FOR hour IN ([0], [1], [2], [3])) AS p

UNION ALL

SELECT systemid, 'AvgDuration' AS [statistics], [0], [1], [2], [3]
FROM callD pivot (max(avgduration) FOR hour IN ([0], [1], [2], [3])) AS p2

ORDER BY systemid, [statistics] DESC;

The output can be seen seen here: http://www.sqlfiddle.com/#!3/eb109/20/0

You have the right idea... unpivot and then pivot. Maybe there is a better way, but this works:

SELECT *
FROM (
    SELECT SystemId, [Hour], [Stat], [Statistics]
    FROM
        (SELECT systemid, [hour], CallStarts, AvgDuration FROM t) nt
    UNPIVOT
        (stat FOR [Statistics] IN (CallStarts, AvgDuration)) AS ut
    ) AS ap
PIVOT
    (SUM (Stat) FOR [Hour] IN ([0], [1], [2], [3], [4])) AS p
ORDER BY [SystemId], [Statistics] DESC

Here is a sqlfiddle showing it working: http://www.sqlfiddle.com/#!3/eb109/8/0

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top