【问题标题】:SQL Server use column value as column names and convert to json arraySQL Server 使用列值作为列名并转换为 json 数组
【发布时间】:2020-12-14 16:27:39
【问题描述】:

假设我有下表 ProductValues:

ProductID Name Value
1 Market A
1 Customer B
2 Market C
2 Customer D

我可以按它们的 ProductID 对它们进行分组,并使用以下代码将这些值作为数组获取:

SELECT
(
    SELECT Name, Value FROM ProductValues
    WHERE P.ID = ProductID
    FOR JSON PATH
)
FROM @ProductIDs P '@ProductIDs is a table containing the productIDs that Id like to retrieve'

这将返回以下内容:

(No column name)
[{"Name":"Market","Value":"A"},{"Name":"Customer","Value":"B"}]
[{"Name":"Market","Value":"C"},{"Name":"Customer","Value":"D"}]

我想使用 Pivot 动态创建键值对。我想实现以下目标:

(No column name)
[{"Market":"A"},{"Customer":"B"}]
[{"Market":"C"},{"Customer":"D"}]

查看另一个答案,我尝试了以下方法,但这不会动态设置键并且不会执行(说明 Pivot 中的“Value”和“TechName”未定义):

SELECT(
    SELECT Market, Customer
    FOR JSON PATH
)
FROM(
    SELECT(
        SELECT Name, Value FROM ProductValues
        WHERE ProductID =  P.ID
    )
    FROM @ProductIDs P
) t
PIVOT(
    MAX(Value)  '<--- "Value" Undefined'
    FOR Name IN ( '<--- "Name" Undefined'
        Market, Customer
    )
) AS pvt
GROUP BY
    Market, Customer

【问题讨论】:

    标签: sql arrays json sql-server pivot


    【解决方案1】:

    您可以使用条件聚合进行旋转,即转换为 JSON:

    select (
        select
            max(case when name = 'Market'   then value end) as market,
            max(case when name = 'Customer' then value end) as customer
        from productvalues pv
        where pv.productid = p.productid
        for json path
    ) as js
    from @ProductIDs p
    

    这是一个demo on DB Fiddle

    【讨论】:

      【解决方案2】:

      SQL Server 在设计上是声明性的。如果您正在寻找动态列,则需要 DYNAMIC SQL

      示例

      Declare @sql nvarchar(max) = stuff( (Select Distinct ','+QUOTENAME(Name) From ProductValues FOR XML PATH('')),1,1,'') 
      
      SET @sql = 'Select B.*
                    From (
                          SELECT '+@sql+'
                          FROM  ProductValues 
                          PIVOT (max([Value]) FOR [Name] IN ('+@sql+')) AS pvt
                         ) A
                   Cross Apply ( (Select A.* for json path ) ) B (JSONData)'
      exec(@sql)
      

      退货

      JSONData
      [{"Customer":"B","Market":"A"}]
      [{"Customer":"D","Market":"C"}]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-31
        相关资源
        最近更新 更多