4

下面的 SELECT 语句来自我用来检索随后发送到 JSON 的数据的存储过程:

SELECT *
FROM (
    SELECT CAST(DateTimeUTC as SmallDateTime) as [DateTime], DataValue, VariableID
    FROM DataValues
    WHERE SiteID = @siteID and VariableID BETWEEN 9 and 10 and DateTimeUTC >= DATEADD (day, @pastDays, getdate())
     ) TableDate
PIVOT (SUM(DataValue) FOR VariableID IN ([9],[10])) PivotTable ORDER BY [DateTime]

我想要完成的是修改过程以接受要旋转的列范围。在上面的示例中,我只检索两个变量的值。如果我想检索 VariableID 1 到 10 或 1 到 50 怎么办?必须有一种方法可以通过以下方式检索 1 到 10:

 VariableID IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10])

MSDN 上的Using PIVOT and UNPIVOT没有提到指定范围的方法。

我意识到可以在存储过程中使用动态 SQL,但考虑到我自己的 SQL 知识以及必须长期维护这一点的人的知识,我不愿通过使用动态 SQL 来引入额外的复杂性。这里有一个概念上类似的问题,请参阅TSQL Pivot Long List of Columns,并用动态 SQL 解决方案回答了这个问题。

4

1 回答 1

6

不幸的是,该PIVOT函数不具备生成列列表的能力,而无需使用动态 sql。

因此,您的 SQL 代码将与此类似:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(VariableID) 
                    from DataValues
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT [DateTime], ' + @cols + ' from 
             (
                SELECT CAST(DateTimeUTC as SmallDateTime) as [DateTime], 
                    DataValue, 
                    VariableID
                FROM DataValues
                WHERE SiteID = '+cast(@siteID as varchar(10))+'
                    -- and VariableID BETWEEN 9 and 10 -- remove the variableID filter
                    and DateTimeUTC >= DATEADD (day, +'cast(@pastDays as varchar(10))+', getdate())
            ) x
            pivot 
            (
                SUM(DataValue)
                for VariableID in (' + @cols + ')
            ) p '

execute(@query)

关键是以下代码生成variableIds要成为列的列表:

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(VariableID) 
                    from DataValues
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

这将创建所有distinct变量 id 的列表。然后将此列表添加到要返回的 SQL 查询字符串中。

于 2013-02-05T22:05:15.200 回答