MS SQL json query/where 子句嵌套数组项

MS SQL json query/where clause nested array items

我有 json 数据,我可以使用 CROSS APPLY OPENJSON( 查询这些数据,一旦您开始添加多个交叉应用或一旦您的 json 文档变得太大,它就会变慢。所以我想在我试图过滤的数据上添加一个索引,但是我无法使用交叉应用来获得嵌套数组项的语法。因此,我无法创建索引,因为您在创建索引时不能使用交叉应用。根据 MS 文档,我应该可以做到

JSON_query(my_column, $.parentItem.nestedItemsArray1.nestedItemsArray2)

我应该能够获取嵌套数组项的所有值,然后通过添加索引来查询并提高性能,就像这样

ALTER TABLE mytable 
ADD vdata AS JSON_query(my_column, 
  $.parentItem.nestedItemsArray1.nestedItemsArray2')  
  
CREATE INDEX idx_json_my_column ON mytable(vdata)

但是上面的 $.array.arrayitems 语法不起作用? 在旁注中,我忍不住用关系术语来思考,通常在 Sql 中你会像这样索引一列数据

col
---
 1| 
 2|
 3|

但是 json 数据似乎变平了,所以当我按照 MS 示例使用 JSON_QUERY 时,我得到“1,2,3”“我假设我想索引一个值数组而不是除非索引将 return 加肥数据的内部数据 ?

我的即插即用工作示例

declare  @mydata table (    
  ID int NOT NULL,  
  jsondata varchar(max) NOT NULL  
)

INSERT INTO @mydata (id, jsondata)
    VALUES (789, '{ "Id": "12345", "FinanceProductResults": [ { "Term": 12, "AnnualMileage": 5000, "Deposits": 0, "ProductResults": [] }, { "Term": 18, "AnnualMileage": 30000, "Deposits": 15000, "ProductResults": [] }, { "Term": 24, "AnnualMileage": 5000, "Deposits": 0, "ProductResults": [ { "Key": "HP", "Payment": 460.28 } ] }, { "Term": 24, "AnnualMileage": 10000, "Deposits": 0, "ProductResults": [ { "Key": "HP", "Payment": 500.32 } ] }]}')

SELECT 
    j_Id
    ,JSON_query (c.value, '$.Term') as Term
    ,JSON_Value (c.value, '$.AnnualMileage') as AnnualMileage
    ,JSON_Value (c.value, '$.Deposits') as Deposits     
    ,JSON_Value (p.value, '$.Key') as [Key]
    ,JSON_Value (p.value, '$.Payment') as Payment
    --,c.value
FROM @mydata  f 
    CROSS APPLY OPENJSON(f.jsondata)
        WITH (j_Id nvarchar(100) '$.Id')
    CROSS APPLY OPENJSON(f.jsondata, '$.FinanceProductResults') AS c
    CROSS APPLY OPENJSON(c.value, '$."ProductResults"') AS p
where 
    ID = 789 
    AND JSON_Value (p.value, '$.Payment') = '460.28'

我正在使用这些 MS 文档来指导我:

How to create an index

How to get data

更新

我能够使用“with”方法略微提高性能

SELECT 
    j_Id,
    FinanceDetails.Term,
    FinanceDetails.AnnualMileage,
    FinanceDetails.Deposits,
    Payments.Payment
FROM @mydata  f 
    CROSS APPLY OPENJSON(f.jsondata)
        WITH (j_Id nvarchar(100) '$.Id')
    OUTER APPLY OPENJSON (f.jsondata, '$.FinanceProductResults' )  
            WITH (   
                Term            INT             '$.Term',  
                AnnualMileage   INT             '$.AnnualMileage',  
                Deposits        INT             '$.Deposits',  
                ProductResults  NVARCHAR(MAX)   '$.ProductResults'  AS JSON  
            ) AS FinanceDetails
        OUTER APPLY OPENJSON(ProductResults,  '$') 
            WITH (   
                Payment DECIMAL(19, 4)          '$.Payment' 
            ) AS Payments
WHERE   
    Payments.Payment = 460.28

但我还是喜欢在子数组数据上添加索引以帮助提高性能?

目前,您无法为嵌套属性编制索引。 全文搜索是可能的选择吗?您可以在 JSON 列上创建 FTS 并添加谓词:

WHERE ....
AND CONTAINS( jsondata, 'NEAR(('Payments,460),1)')

因为 JSON 是文本,这个谓词将过滤掉所有没有类似 "Payment" 和 460 的记录(这将识别 key:value 对) ,您可以对减少的行集应用 CROSS APPLY。