Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 具有多条记录的透视表_Sql_Sql Server_Stored Procedures - Fatal编程技术网

Sql 具有多条记录的透视表

Sql 具有多条记录的透视表,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我的数据结构如下: LocationId, GroupId, DayOfWeek, Count, DatetimeValue15Min 2 9 4 5 2014-01-02 08:15:00.000 2 9 4 5 2014-01-02 09:15:00.000 我想计算每天的模式,上面的数据已经包含了解模式的计数。我已经编写了一个带有枢轴的查询 SELEC

我的数据结构如下:

LocationId, GroupId, DayOfWeek, Count,  DatetimeValue15Min
2            9         4         5      2014-01-02 08:15:00.000
2            9         4         5      2014-01-02 09:15:00.000    
我想计算每天的模式,上面的数据已经包含了解模式的计数。我已经编写了一个带有枢轴的查询

SELECT 
    pvt.LocationId, pvt.GroupId, [1], [2], [3], [4],[5]
FROM 
    @TempResult
PIVOT
    (min ([DatetimeValue15Min])
     FOR DayOfWeek IN ( [1], [2], [3], [4],[5])) AS pvt
在本例中,我有两种模式,但我想同时显示它们。在这种情况下,我的查询只返回具有最小值的模式。我知道我可以用最大值进行第二次查询,但如果我有两种以上的模式呢

输出应如下所示:

LocationId  GroupId    1          2           3       4               5
2             9                                       08:15, 09:15
我正在使用SQLServer2005

SELECT LocationId, GroupId
    , STUFF (
          MAX (CASE WHEN DayOfWeek = 1 AND num = 1 THEN Value ELSE '' END)
        + MAX (CASE WHEN DayOfWeek = 1 AND num = 2 THEN Value ELSE '' END), 1, 2, '') AS [1]
    , STUFF (
          MAX (CASE WHEN DayOfWeek = 2 AND num = 1 THEN Value ELSE '' END)
        + MAX (CASE WHEN DayOfWeek = 2 AND num = 2 THEN Value ELSE '' END), 1, 2, '') AS [2]
    , STUFF (
          MAX (CASE WHEN DayOfWeek = 3 AND num = 1 THEN Value ELSE '' END)
        + MAX (CASE WHEN DayOfWeek = 3 AND num = 2 THEN Value ELSE '' END), 1, 2, '') AS [3]
    , STUFF (
          MAX (CASE WHEN DayOfWeek = 4 AND num = 1 THEN Value ELSE '' END)
        + MAX (CASE WHEN DayOfWeek = 4 AND num = 2 THEN Value ELSE '' END), 1, 2, '') AS [4]
    , STUFF (
          MAX (CASE WHEN DayOfWeek = 5 AND num = 1 THEN Value ELSE '' END)
        + MAX (CASE WHEN DayOfWeek = 5 AND num = 2 THEN Value ELSE '' END), 1, 2, '') AS [5]
FROM (
    SELECT LocationId, GroupId, DayOfWeek, ', ' + CONVERT (VARCHAR(5), DatetimeValue15Min, 8) AS Value
        , ROW_NUMBER() OVER(PARTITION BY LocationId, GroupId, DayOfWeek ORDER BY DatetimeValue15Min) AS num
    FROM @TempResult
) T
GROUP BY LocationId, GroupId
UPD。解决方案每天的值数量不限

WITH cte AS (
    SELECT LocationId, GroupId, DayOfWeek, CONVERT (VARCHAR(5), DatetimeValue15Min, 8) AS Value
        , ROW_NUMBER() OVER(PARTITION BY LocationId, GroupId, DayOfWeek ORDER BY DatetimeValue15Min) AS num
    FROM @TempResult
)

SELECT LocationId, GroupId
    , MIN (CASE DayOfWeek WHEN 1 THEN Value END) AS [1]
    , MIN (CASE DayOfWeek WHEN 2 THEN Value END) AS [2]
    , MIN (CASE DayOfWeek WHEN 3 THEN Value END) AS [3]
    , MIN (CASE DayOfWeek WHEN 4 THEN Value END) AS [4]
    , MIN (CASE DayOfWeek WHEN 5 THEN Value END) AS [5]
FROM (
    SELECT DISTINCT c1.LocationId, c1.GroupId, c1.DayOfWeek
        , STUFF ( (
            SELECT ', ' + c2.Value
            FROM cte c2
            WHERE c1.LocationId = c2.LocationId AND c1.GroupId = c2.GroupId AND c1.DayOfWeek = c2.DayOfWeek
            FOR XML PATH ('')
        ), 1, 2, '') AS Value
    FROM cte c1
) t
GROUP BY LocationId, GroupId

你就快到了。您只需要构建逗号分隔的列表。对于这一点,稍微滥用xml类型非常有效

;WITH
t1 AS ( --Add a grouping id for quick reference
  SELECT
    [LocationId],[GroupId],[DayOfWeek],[DatetimeValue15Min],
    DENSE_RANK() OVER(ORDER BY [LocationId],[GroupId],[DayOfWeek]) [i]
  FROM @TempResult
),
t2 AS ( --Build a comma-separated list of all [DatetimeValue15Min] with same grouping id
  SELECT [LocationId],[GroupId],[DayOfWeek],
    CAST(REPLACE((SELECT CONVERT(time, [DatetimeValue15Min]) AS a FROM t1 WHERE [i] = t.[i] FOR xml PATH('')),'</a><a>',',') AS xml).value('a[1]','varchar(max)') [dtv_list]
  FROM t1 t
)
SELECT pvt.LocationId, pvt.GroupId, [1], [2], [3], [4],[5]
                FROM t2

                PIVOT
                (
                    min ([dtv_list])
                    FOR DayOfWeek IN ( [1], [2], [3], [4],[5])
                ) AS pvt
xml技巧的工作原理如下:

为XML选择[DatetimeValue15Min]->08:1509:15 替换为“,”->08:15,09:15 从xml提取第一个节点->“08:15,09:15”
GriGrim:如果有两个以上的模式值怎么办?如果不使用别名a,Xml技巧效果更好。请参阅我的第二个解决方案。