SQL将CTE生成的行转换为列-包括字段名

时间:2019-07-11 02:57:07

标签: sql-server pivot common-table-expression

我有一个CTE,可以将数据生成为可变数量的行。这些是我每小时在连接到另一个表时需要使用的值,但是那部分在这里并不重要。

仅CTE部分如下所示:

DECLARE @interval INT = 3 -- hours
DECLARE @period INT = 24 -- hours
;WITH cteHour AS (
    SELECT CAST('i0' AS VARCHAR(6)) AS fieldname, 0 AS i, 0 AS startpos
    UNION ALL
    SELECT CONCAT('i', CAST(i + 1 AS VARCHAR(5))) AS fieldname, i + 1 AS i, startpos + @interval AS startpos
    FROM cteHour
    WHERE (startpos + @interval) < @period
) SELECT fieldname, startpos FROM cteHour

它会生成这样的数据(取决于@interval@period的值):

fieldname startpos
--------- -----------
i0        0
i1        3
i2        6
i3        9
i4        12
i5        15
i6        18
i7        21

我的问题是,如何使用第一列作为字段名称,将结果分成列而不是行,如下所示:

i0 i1 i2 i3 i4 i5 i6 i7
-- -- -- -- -- -- -- --
0  3  6  9  12 15 18 21

我猜测它将需要一个PIVOT,但是据我所知,透视不能动态生成字段名称。因此,我愿意接受完成工作的所有答案。

3 个答案:

答案 0 :(得分:0)

由于它需要动态sql,因此跳过枢轴部分并直接从cte生成动态查询

DECLARE @sql NVARCHAR(MAX)

SELECT  @sql    = isnull(@sql + ',', 'select ')
                + quotename(fieldname) + '=' + convert(varchar(10), startpos)
FROM    cteHour
order by startpos 

print   @sql

exec    sp_executesql @sql

答案 1 :(得分:0)

以下查询应该执行您想要的操作,它使用一个临时表,但您会对该方法有一个了解

editor.occurrencesHighlight

答案 2 :(得分:0)

这是使用动态查询的最简单答案

DECLARE @interval INT = 3 -- hours
DECLARE @period INT = 24 -- hours
DECLARE @startpos INT = 0
DECLARE @i INT = 0
DECLARE @sql NVARCHAR(MAX) = 'SELECT '
WHILE @startpos < @period
BEGIN
    SET @sql = @sql + (CASE WHEN @i > 0 THEN ',' ELSE '' END) +
    CAST(@startpos AS VARCHAR(5)) + ' AS i' + CAST(@i AS VARCHAR(5))

    SET @i = @i + 1
    SET @startpos = @startpos + @interval
END
print @sql
exec sp_executesql @sql