简体   繁体   English

带有动态列的数据透视TSQL表

[英]Pivot TSQL table with dynamic columns

I am passing up JSON as a parameter to a SQL stored proc. 我将JSON作为参数传递给SQL存储过程。 I use a function that takes a JSON dictionary and creates a table with key value pairs (two columns) that I then use with a COALESCE to create dynamic sql for an INSERT statement. 我使用一个使用JSON字典并创建具有键值对(两列)的表的函数,然后将其与COALESCE一起用于为INSERT语句创建动态sql。 This works fine for a single dictionary, but I need to also be able to send up JSON string that contains an array of dictionaries. 这对于单个字典来说效果很好,但是我还需要能够发送包含字典数组的JSON字符串。 Right now, my parse function gives me this table variable: 现在,我的解析函数给了我这个表变量:

在此处输入图片说明

What I need is a table variable like this: 我需要的是一个这样的表变量:

在此处输入图片说明

I can get the column names from the first table with this: 我可以从第一个表中获取列名称:

SELECT DISTINCT element name from @JSONTable

I should mention that these elementname's can and will change. 我应该提到,这些elementname可以并且将会改变。 I will not know the number of distinct elementname values. 我将不知道不同的elementname值的数量。

UPDATE - Using Umair's answer, I am getting close: 更新-使用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

But the dictionary values don't correspond to the key. 但是字典值与键不对应。 Here is the results of Umair's current answer: 这是Umair当前答案的结果: 在此处输入图片说明

How about 怎么样

--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

ie dynamic pivoting :) 即动态枢轴:)

Edit: 编辑:

Since you do not want to aggregate by anything in the pivot, I added a row number function to assign each distinct elementname a sequentially increasing id (based on element value). 由于您不希望通过数据透视表中的任何内容进行聚合,因此我添加了一个行号功能,为每个不同的elementname分配一个按顺序递增的id(基于element值)。 This will essentially group the pivot by this row column, producing all the required rows. 这实际上将按此行列将数据透视表分组,从而生成所有必需的行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM