【问题标题】:Having trouble with MS Sql Server OPENJSON featureMS Sql Server OPENJSON 功能有问题
【发布时间】:2021-09-30 19:54:26
【问题描述】:

我为这个问题在下面创建了一个 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

按原样运行此脚本会产生以下输出:

Id Attributes Step State
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] A A
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] A Active
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] Active A
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] Active Active
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] B B
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] B Inactive
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] Inactive B
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] Inactive Inactive
3 [{"Name":"State","Value":"Active"}] Active Active
4 [{"Name":"Step","Value":"D"}] D D

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

Id Attributes Step State
1 [{"Name":"Step","Value":"A"},{"Name":"State","Value":"Active"}] A Active
2 [{"Name":"Step","Value":"B"},{"Name":"State","Value":"Inactive"}] B Inactive
3 [{"Name":"State","Value":"Active"}] Active
4 [{"Name":"Step","Value":"D"}] D

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

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

非常感谢您的帮助!

【问题讨论】:

    标签: sql-server open-json


    【解决方案1】:

    可以使用条件聚合:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      相关资源
      最近更新 更多