【问题标题】:Extract Array Element From JSON Using T-SQL使用 T-SQL 从 JSON 中提取数组元素
【发布时间】:2020-06-22 19:55:29
【问题描述】:

我有一个来自 Google Geocoding API 的以下响应字符串,存储在 SQL Server 数据库中:

{
   "results":[
      {
         "address_components":[
            {
               "long_name":"Khalifa City",
               "short_name":"Khalifa City",
               "types":[
                  "political",
                  "sublocality",
                  "sublocality_level_1"
               ]
            },
            {
               "long_name":"Abu Dhabi",
               "short_name":"Abu Dhabi",
               "types":[
                  "locality",
                  "political"
               ]
            },
            {
               "long_name":"Abu Dhabi",
               "short_name":"Abu Dhabi",
               "types":[
                  "administrative_area_level_1",
                  "political"
               ]
            },
            {
               "long_name":"United Arab Emirates",
               "short_name":"AE",
               "types":[
                  "country",
                  "political"
               ]
            }
         ],
         ...
      }
   ],
   "status":"OK"
}

我的任务是从上面的 JSON 中提取 Country 和 City。我检查了数据,似乎 Geocoding API 并不总是在 address_component 节点中返回 4 个元素,因此我需要在数组中获取类型包含城市的 administrative_area_level_1 的元素,这在逻辑上应该是这样的:

JSON_QUERY([Json], '$.results[0].address_components<where types = administrative_area_level_1>.short_name')

【问题讨论】:

    标签: sql json sql-server json-query json-value


    【解决方案1】:

    这就是我过去解决这个问题的方式。您可以在 SSMS 中运行它:

    DECLARE @json AS VARCHAR(1000) = '{ "results":[ { "address_components":[
        { "long_name":"Khalifa City", "short_name":"Khalifa City", "types":[ "political", "sublocality", "sublocality_level_1" ] },
        { "long_name":"Abu Dhabi", "short_name":"Abu Dhabi", "types":[ "locality", "political" ] },
        { "long_name":"Abu Dhabi", "short_name":"Abu Dhabi", "types":[ "administrative_area_level_1", "political" ] },
        { "long_name":"United Arab Emirates", "short_name":"AE", "types":[ "country", "political" ] }
    ] } ], "status":"OK" }';
    
    SELECT
        Addresses.long_name, Addresses.short_name, Addresses.[types]
    FROM OPENJSON ( @json, '$.results' ) WITH (
        addresses NVARCHAR(MAX) '$.address_components' AS JSON
    ) AS j
    CROSS APPLY (
    
        SELECT * FROM OPENJSON ( j.addresses ) WITH (
            long_name VARCHAR(50) '$.long_name',
            short_name VARCHAR(50) '$.short_name',
            [types] NVARCHAR(MAX) '$.types' AS JSON
        ) AS Names
        CROSS APPLY OPENJSON ( [types] ) AS [Types]
        WHERE [Types].[value] = 'administrative_area_level_1'
    
    ) AS Addresses;
    

    返回

    +-----------+------------+------------------------------------------------+
    | long_name | short_name |                     types                      |
    +-----------+------------+------------------------------------------------+
    | Abu Dhabi | Abu Dhabi  | [ "administrative_area_level_1", "political" ] |
    +-----------+------------+------------------------------------------------+
    

    【讨论】:

      【解决方案2】:

      如果我理解了这个问题并且您想解析输入 JSON(即使 $.results JSON 数组有多个项目),以下方法可能会有所帮助:

      JSON:

      DECLARE @json nvarchar(max) = N'{
         "results":[
            {
               "address_components":[
                  {"long_name":"Khalifa City", "short_name":"Khalifa City", "types":["political", "sublocality", "sublocality_level_1"]},
                  {"long_name":"Abu Dhabi", "short_name":"Abu Dhabi", "types":["locality", "political"]},
                  {"long_name":"Abu Dhabi", "short_name":"Abu Dhabi", "types":["administrative_area_level_1", "political"]},
                  {"long_name":"United Arab Emirates", "short_name":"AE", "types":["country", "political"]}
               ]
            }
         ],
         "status":"OK"
      }'
      

      声明:

      SELECT j2.long_name, j2.short_name
      FROM OPENJSON(@json, '$.results') j1
      CROSS APPLY OPENJSON(j1.value, '$.address_components') WITH (
         long_name varchar(100) '$.long_name',
         short_name varchar(100) '$.short_name',
         types nvarchar(max) '$.types' AS JSON
      ) j2
      CROSS APPLY OPENJSON(j2.types) j3
      WHERE j3.[value] = 'administrative_area_level_1'
      

      输出:

      long_name   short_name
      ----------------------
      Abu Dhabi   Abu Dhabi
      

      【讨论】:

        猜你喜欢
        • 2023-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-21
        • 1970-01-01
        • 2019-07-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多