使用动态列透视SQL表

时间:2014-01-25 15:23:33

标签: sql sql-server json

我将JSON作为参数传递给SQL存储过程。我使用一个函数,它接受一个JSON字典并创建一个带有键值对(两列)的表,然后我使用COALESCEINSERT语句创建动态sql。这适用于单个字典,但我还需要能够发送包含字典数组的JSON字符串。现在,我的解析函数给了我这个表变量:

enter image description here

我需要的是一个像这样的表变量:

enter image description here

我可以从第一个表中获取列名:

SELECT DISTINCT element name from @JSONTable

我应该提到这些元素名称可以而且会改变。我不知道不同的elementname值的数量。

更新 - 使用Umair的回答,我越来越近了:

DECLARE @JSONString AS VARCHAR(MAX)

SET @JSONString = '[{"ravid":3,"ravversion":2,"taskid":3},{"ravid":4,"ravversion":7,"taskid":99}]'

IF OBJECT_ID('tempdb..#JSONTable') IS NOT NULL
    DROP TABLE #JSONTable


CREATE TABLE #JSONTable
            (
              elementname VARCHAR(500) ,
              elementvalue VARCHAR(500)
            )
        INSERT  INTO #JSONTable
                ( elementname ,
                  elementvalue

                )
                SELECT  NAME ,
                        StringValue
                FROM    dbo.parseJSON(@JSONString)
                WHERE   LEN(StringValue) > 0 AND NAME IS NOT NULL



--declare a csv variable with all the distinct elements
DECLARE @csv NVARCHAR(max) = STUFF(
    (
         SELECT ',' + elementname
         FROM (
              SELECT DISTINCT elementname
              FROM #JSONTable
         ) AS e
         FOR XML PATH(''), TYPE
    ).value('.', 'nvarchar(max)'),
    1,
    1,
    ''
);

DECLARE @sql NVARCHAR(MAX) = '
    SELECT *
    FROM (
       SELECT *, Row = ROW_NUMBER() OVER (PARTITION BY elementname ORDER BY elementname)
       FROM #JSONTable
    ) AS t
    PIVOT (
        MAX(elementvalue)
        FOR elementname IN (' + @csv + ')
    ) AS p
'

EXEC sp_executesql @sql

但字典值并不对应于键。以下是Umair当前答案的结果: enter image description here

1 个答案:

答案 0 :(得分:0)

怎么样

--declare a csv variable with all the distinct elements
DECLARE @csv NVARCHAR(max) = STUFF(
    (
         SELECT ',' + elementname
         FROM (
              SELECT DISTINCT elementname
              FROM #JSONTable
         ) AS e
         FOR XML PATH(''), TYPE
    ).value('.', 'nvarchar(max)'),
    1,
    1,
    ''
);

DECLARE @sql NVARCHAR(MAX) = '
    SELECT *
    FROM (
       SELECT *, Row = ROW_NUMBER() OVER (PARTITION BY elementname ORDER BY elementvalue)
       FROM #JSONTable
    ) AS t
    PIVOT (
        MAX(elementvalue)
        FOR elementname IN (' + @csv + ')
    ) AS p
'

EXEC sp_executesql @sql

即动态旋转:)

编辑:

由于您不希望通过pivot中的任何内容进行聚合,因此我添加了一个行号函数,以便为每个不同的元素名分配一个顺序递增的id(基于元素值)。这将基本上按此行列对枢轴进行分组,从而生成所有必需的行。