在 SQL Server 2016 中获取 json 数组的长度

Posted

技术标签:

【中文标题】在 SQL Server 2016 中获取 json 数组的长度【英文标题】:Get length of json array in SQL Server 2016 【发布时间】:2017-08-25 19:07:37 【问题描述】:

您知道 SQL Server 2016 中新的 JSON_ 支持,所以 假设我连续有这些数据


  "BaseBoarding": 1,
  "PriceLineStrategy": "PerPersonPerNight",
  "Currency": "EUR",
  "BasePriceLineList": [
    
      "RoomTypeId": 1,
      "PeriodId": 1,
      "Price": 10.0
    ,
    
      "RoomTypeId": 1,
      "PeriodId": 2,
      "Price": 100.0
    ,
    
      "RoomTypeId": 1,
      "PeriodId": 3,
      "Price": 190.0
    ,
    
      "RoomTypeId": 2,
      "PeriodId": 1,
      "Price": 280.0
    ,
    
      "RoomTypeId": 2,
      "PeriodId": 2,
      "Price": 310.0
    ,
    
      "RoomTypeId": 2,
      "PeriodId": 3,
      "Price": 340.0
    
  ]

如何以最高效的方式获取“BasePriceLineList”的项目数,最好使用内置的 JSON 支持?

需要这样写:

SELECT JSON_ARRLEN(JsonDataCol, '$.BasePriceline') FROM MyTable
WHERE Id = 1

结果为 6。

【问题讨论】:

【参考方案1】:

大量挖掘,我的结论是使用它。如果您想查看找到的查询元素,请删除计数。使用 SQL Server 2019

SELECT 
COUNT(JSON_QUERY(JsonObject, '$.[0].Region')) AS RegionCount
FROM YourTable

【讨论】:

这种方法不可靠。以下返回 1,而不是预期的 0:select count(json_query('[]', 'strict $'))【参考方案2】:

假设的 SQL 语句:

SELECT JSON_ARRLEN(JsonDataCol, '$.BasePriceline') FROM MyTable

可以通过实际语句来完成:

SELECT (SELECT COUNT(*) FROM OPENJSON(JsonDataCol, '$.BasePriceline')) FROM MyTable

【讨论】:

【参考方案3】:

在进行一些临时数据审查时,我曾多次遇到这个基本需求。所以我继续创建了一个很小的标量函数来非常通用地做到这一点。内置的假设很少,您可能需要使用isnull 和/或使用json_value 来提取您尝试检查的嵌套数组。另外,我真的不知道这在任何规模上都会对性能产生什么影响,我一次只需要对几十条记录执行此操作。只是想我会分享一下,以防其他人在这里寻找一种相当通用的方法。

注意:在此使用了一些 hacky“技巧”,例如确保函数在无效的 JSON 数组上引发错误,即使函数内部不允许使用 throw。额外除以零是为了以防任何人的隐式转换设置非常宽松,而这只是我在其他地方使用的模式,其中字符串返回是有效的。

create function array_length (@array nvarchar(max))
returns int as begin
  if (@array is null or isjson(@array) != 1
      or left(@array, 1) + right(@array, 1) <> '[]')
    return 'Invalid JSON array provided to array_length' + (1/0)
  return (select count(*) from openjson(@array))
end

【讨论】:

【参考方案4】:

使用表格代替变量:

SELECT count(priceLineLists.RoomTypeId)
FROM Mytable
CROSS APPLY OPENJSON (JsonDataCol, N'$.BasePriceLineList')
  WITH (
    RoomTypeId int)
      AS priceLineLists

【讨论】:

我会将其标记为正确答案,因为它可以同时用于多行。【参考方案5】:

您可以将其转换为数据集,然后计算行数:

DECLARE @JSON NVARCHAR(4000) = N'
  "BaseBoarding": 1,
  "PriceLineStrategy": "PerPersonPerNight",
  "Currency": "EUR",
  "BasePriceLineList": [
    
      "RoomTypeId": 1,
      "PeriodId": 1,
      "Price": 10.0
    ,
    
      "RoomTypeId": 1,
      "PeriodId": 2,
      "Price": 100.0
    ,
    
      "RoomTypeId": 1,
      "PeriodId": 3,
      "Price": 190.0
    ,
    
      "RoomTypeId": 2,
      "PeriodId": 1,
      "Price": 280.0
    ,
    
      "RoomTypeId": 2,
      "PeriodId": 2,
      "Price": 310.0
    ,
    
      "RoomTypeId": 2,
      "PeriodId": 3,
      "Price": 340.0
    
  ]
'

select COUNT(*) 
FROM OPENJSON(@json, N'$.BasePriceLineList')
WITH (RoomTypeID varchar(100) '$.RoomTypeId')

【讨论】:

以上是关于在 SQL Server 2016 中获取 json 数组的长度的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 和 C# 中获取最后插入的字符串 ID

Microsoft SQL Server 2016,T-SQL:根据各个日期获取数据集的日期范围

在 SQL Server 2016 中调试一个关于存储过程执行的奇怪场景

从SQL Server数据库中的文件路径获取文件信息

我的 R 代码没有从 SQL Server 获取数据

如何在 SQL Server 中获取一个季度的上个月数据?