MS Sql 服务器 OPENJSON 功能出现问题

Having trouble with MS Sql Server OPENJSON feature

我在下面为这个问题创建了一个 sql 测试脚本。

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

CREATE TABLE #temp
(
    Id INT NOT NULL PRIMARY KEY
  , Attributes NVARCHAR(MAX) NULL
);

INSERT INTO #temp (Id, Attributes)
VALUES (1, '[{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}]');
INSERT INTO #temp (Id, Attributes)
VALUES (2, '[{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}]');
INSERT INTO #temp (Id, Attributes)
VALUES (3, '[{"Name":"State","Value":"Active"}]');
INSERT INTO #temp (Id, Attributes)
VALUES (4, '[{"Name":"Step","Value":"D"}]');

SELECT
    t.Id
  , t.Attributes
  , stepname.Value AS [Step]
  , statename.Value AS [State]
FROM #temp t
    CROSS APPLY
    OPENJSON(t.Attributes)
    WITH
    (
        Name NVARCHAR(MAX) '$.Name'
      , Value NVARCHAR(MAX) '$.Value'
    ) AS stepname
    CROSS APPLY
    OPENJSON(t.Attributes)
    WITH
    (
        Name NVARCHAR(MAX) '$.Name'
      , Value NVARCHAR(MAX) '$.Value'
    ) AS statename
WHERE 1 = 1
      --AND (stepname.Name = statename.Name)     -- A
      --AND                                      -- B
      --(                                        -- B
      --    stepname.Name IS NULL                -- B
      --    OR stepname.Name = 'Step'            -- B
      --)                                        -- B
      --AND                                      -- B
      --(                                        -- B
      --    statename.Name IS NULL               -- B
      --    OR statename.Name = 'State'          -- B
      --);                                       -- B

运行 该脚本按原样给出以下输出:

编号 属性 步骤
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] 一个 一个
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] 一个 有效
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] 有效 一个
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] 有效 有效
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] B B
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] B 无效
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] 无效 B
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] 无效 无效
3 [{"名称":"状态","值":"有效"}] 有效 有效
4 [{"名称":"步骤","值":"D"}] D D

虽然我希望在输出中看到只有 4 行,每个数据行一行。

编号 属性 步骤
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] 一个 有效
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] B 无效
3 [{"名称":"状态","值":"有效"}] 有效
4 [{"名称":"步骤","值":"D"}] D

我在我的示例中留下了一些注释代码,以查看我尝试过但都无济于事的事情类型。用 '-- A' 取消注释 where 语句让我更接近,但不完全。我确信取消注释 where 子句中末尾带有“-- B”的语句会给我想要的东西,但事实并非如此。关于如何做到这一点有什么想法吗?

我最初只有 1 个 OPENJSON 块,但没有成功,所以我认为也许有 2 个 OPENJSON 块,一个用于 Step,一个用于 State 会有所帮助,但仍然无法包含第 3 行和第 4 行数据,因为这些行中的每一行都缺少 2 个 JSON 值之一。

非常感谢您的帮助!

可以使用条件聚合:

SELECT
    t.Id
  , t.Attributes
  , [Step] = MAX(CASE WHEN stepname.Name = 'Step' THEN stepname.Value END)
  , [State] = MAX(CASE WHEN statename.Name = 'State' THEN statename.Value END) 
FROM #temp t
CROSS APPLY OPENJSON(t.Attributes) WITH (
        Name NVARCHAR(MAX) '$.Name'
      , Value NVARCHAR(MAX) '$.Value'
    ) AS stepname
CROSS APPLY OPENJSON(t.Attributes) WITH (
        Name NVARCHAR(MAX) '$.Name'
      , Value NVARCHAR(MAX) '$.Value'
    ) AS statename
GROUP BY t.Id, t.Attributes
ORDER BY t.Id;

db<>fiddle demo