【问题标题】:Select last value from Json array从 Json 数组中选择最后一个值
【发布时间】:2019-03-13 04:59:05
【问题描述】:

我需要从 JSON 格式中获取数组中的最后一项。我有这个 JSON。

  @json =   
  N'{ 
        "solution": "xxxxxxxxxxxxxxxxxxxxx",
        "options": [
            {
                "choice_id": 205073,
                "choice": "aaaa"
            },
            {
                "choice_id": 205074,
                "choice": "bbbb"
            },
            {
                "choice_id": 205075,
                "choice": "cccc"
            },
            {
                "choice_id": 205076,
                "choice": "dddd"
            }
        ],
    }'  

我想得到

  @json =   
  N'{ 
        "solution": "xxxxxxxxxxxxxxxxxxxxx",
        "options": {
              "choice_id": 205076,
              "choice": "dddd"
        }
    }

我怎样才能达到这个结果?

【问题讨论】:

  • 拥有 4k 声望,您应该已经对 How to Ask 相当熟悉 - 您需要向我们展示您的尝试。
  • @ZoharPeled 这就是重点,我没有尝试过任何东西,因为我不知道如何...... sql 中的这个 JSON 东西对我来说很新,我找不到任何可以帮助我实现的信息那个。
  • 嗯,你应该从reading the documentation...开始
  • @ZoharPeled 我做到了,找不到与我想要实现的目标相关的任何内容
  • 你怎么知道你想要"choice": "dddd"的记录?

标签: json sql-server tsql sql-server-2016


【解决方案1】:

你可以试试这个

DECLARE @json NVARCHAR(MAX) =   
N'{ 
    "solution": "xxxxxxxxxxxxxxxxxxxxx",
    "options": [
        {
            "choice_id": 205073,
            "choice": "aaaa"
        },
        {
            "choice_id": 205074,
            "choice": "bbbb"
        },
        {
            "choice_id": 205075,
            "choice": "cccc"
        },
        {
            "choice_id": 205076,
            "choice": "dddd"
        }
    ]
}';

SELECT TOP 1 
         A.solution
        ,JSON_QUERY(B.[value]) AS options
FROM OPENJSON(@json) WITH (solution nvarchar(max), options NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.options) B
ORDER BY B.[key] DESC
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;

结果

{"solution":"xxxxxxxxxxxxxxxxxxxxx"
,"options":{
            "choice_id": 205076,
            "choice": "dddd"
           }
}

一些解释

FROM OPENJSON 将深入您的 JSON 并找到 顶级 元素。我们按原样获取solution ,并声明AS JSON 以供options 指定,该值稍后将被视为JSON。

CROSS APPLY 将再次调用OPENJSON,但这次是针对options,我们将返回一个数组。 key 列是数组中的序号位置,因此我们可以使用TOP 1ORDER BY key DESC 来获取数组中的最后一个元素。

在我们可以将此查询重新组合为 JSON 之前,我们必须将 B.value 包装为 JSON_QUERY()。否则,我们会在 JSON 中看到转义字符,例如 \t\r\n。原因:如果没有这个,JSON 字符串将不会被视为 JSON 字符串,而是任何其他字符串,并将作为单个文本值打包到结果中。

【讨论】:

    【解决方案2】:

    您可以使用 OPENJSON 切碎并重新组合 JSON 文档(请参阅@digital.aaron 的答案),或使用 JSON_MODIFY,如下所示:

     declare @json nvarchar(max) =   
      N'{ 
            "solution": "xxxxxxxxxxxxxxxxxxxxx",
            "options": [
                {
                    "choice_id": 205073,
                    "choice": "aaaa"
                },
                {
                    "choice_id": 205074,
                    "choice": "bbbb"
                },
                {
                    "choice_id": 205075,
                    "choice": "cccc"
                },
                {
                    "choice_id": 205076,
                    "choice": "dddd"
                }
            ]
        }'  
    
    
    declare @options nvarchar(max) = (
        select top 1 value 
        from openjson(@json,'$.options')
        order by [key] desc 
    );
    
    set @json = json_modify(@json, '$.options', json_query(@options))
    
    select  @json
    

    输出

    { 
            "solution": "xxxxxxxxxxxxxxxxxxxxx",
            "options": {
                    "choice_id": 205076,
                    "choice": "dddd"
                }
        }
    

    请注意,JSON_QUERY 函数也用于将字符串解析为 JSON 片段。否则,@options 中的值将作为单个字符串值插入,而不是 json 对象。

    【讨论】:

      【解决方案3】:

      首先,您的 JSON 字符串格式不正确。您需要删除结束数组括号后的逗号。

      所以让我们声明我们的变量:

      DECLARE @json NVARCHAR(MAX) = N'{ 
              "solution": "xxxxxxxxxxxxxxxxxxxxx",
              "options": [
                  {
                      "choice_id": 205073,
                      "choice": "aaaa"
                  },
                  {
                      "choice_id": 205074,
                      "choice": "bbbb"
                  },
                  {
                      "choice_id": 205075,
                      "choice": "cccc"
                  },
                  {
                      "choice_id": 205076,
                      "choice": "dddd"
                  }
              ]
          }'
      

      现在您可以使用OPENJSON()FOR JSON 的组合来获取数组中的最后一条记录。

      SELECT jsonfield = CAST((
                                  SELECT TOP 1
                                      j.solution
                                      ,o.choice_id
                                      ,o.choice
                                  FROM
                                      OPENJSON(@json)
                                      WITH
                                      (
                                          solution VARCHAR(MAX) '$.solution'
                                          ,options NVARCHAR(MAX) '$.options' AS JSON
                                      ) j
                                  CROSS APPLY
                                      OPENJSON(options)
                                      WITH
                                      (
                                          choice_id INT '$.choice_id'
                                          ,choice VARCHAR(4) '$.choice'
                                      ) o
                                  ORDER BY o.choice_id DESC
                                  FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
                              ) AS NVARCHAR(MAX))
      

      编辑:

      如果您不想按任何节点值排序,也可以使用此查询:

      SELECT jsonfield = CAST((
                                  SELECT TOP 1
                                      j.solution
                                      --,o.*
                                      ,c.choice_id
                                      ,c.choice
                                  FROM OPENJSON(@json)
                                  WITH
                                      (
                                          solution VARCHAR(MAX) '$.solution'
                                          ,options NVARCHAR(MAX) '$.options' AS JSON
                                      ) j
                                  CROSS APPLY OPENJSON(options) o
                                  CROSS APPLY OPENJSON(o.Value) 
                                  WITH (
                                          choice_id int '$.choice_id',
                                          choice varchar(4) '$.choice'
                                          ) c
                                  ORDER BY [key] DESC
                                  FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
                              ) AS NVARCHAR(MAX))
      

      【讨论】:

      • 有一些APPLYs 是多余的,o 别名一个和最后一个。在我的回答中,您将了解如何在value 上使用JSON_QUERY,以便按原样使用对象。
      猜你喜欢
      • 1970-01-01
      • 2017-02-05
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多