简体   繁体   English

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

[英]MS SQL json query/where clause nested array items

I have json data that i can query on using CROSS APPLY OPENJSON( which gets slow once you start adding multiple cross applies or once your json document get too large. So i wanted to add an index on the data im trying to filter on, but i cant get the syntax on nested array items to work with out using a cross apply. As such i cant create an index as you cant use a cross apply when making an index. According to the MS docs i should just be able to do我有可以使用CROSS APPLY OPENJSON(查询的 json 数据CROSS APPLY OPENJSON(一旦你开始添加多个交叉应用或一旦你的 json 文档变得太大,它就会变慢。所以我想在我试图过滤的数据上添加一个索引,但是我无法使用交叉应用来获取嵌套数组项的语法。因此,我无法创建索引,因为在创建索引时您不能使用交叉应用。根据 MS 文档,我应该能够做到

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

I should be able to get all the values of the nested, array items to then query on and improve performance by adding an index, something like this我应该能够获取嵌套数组项的所有值,然后通过添加索引来查询并提高性能,就像这样

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

but the above $.array.arrayitems syntax doesn't work ?但是上面的$.array.arrayitems语法不起作用? On a side note, I cant help but think in relational terms where normally in Sql you would index a column of data like so附带说明一下,我不禁用关系术语来思考,通常在 Sql 中,您会像这样索引一列数据

col
---
 1| 
 2|
 3|

But json data seem to get flattened so when i use JSON_QUERY as per MS example i get "1,2,3" " I assume i want to incdex an array of values rather than a flattened version unless the index will return the inner data of the fattened data ?但是 json 数据似乎变平了,所以当我按照 MS 示例使用 JSON_QUERY 时,我得到“1,2,3”“我假设我想索引一个值数组而不是一个扁平版本,除非索引将返回内部数据肥大的数据?

my plug and play working example我的即插即用工作示例

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'

I'm using these MS docs to guide me :我正在使用这些 MS 文档来指导我:

How to create an index如何创建索引

How to get data如何获取数据

Update更新

I was able to improve performance slightly using the "with" method我能够使用“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

but i still like to add an index on the sub array data to aid in improving performance ?但我仍然喜欢在子数组数据上添加索引以帮助提高性能?

Currently, you cannot index nested properties.目前,您无法索引嵌套属性。 Is Full-text search possible option?是否可以选择全文搜索? You might create FTS on JSON column and add predicate:您可以在 JSON 列上创建 FTS 并添加谓词:

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

Since JSON is text, this predicate will filter out all records that don't have something like "Payment" and 460 near to each other (this will identify key:value pairs), and you can apply CROSS APPLY on the reduced set of rows.由于 JSON 是文本,此谓词将过滤掉所有没有类似“Payment”和 460 之类的东西彼此接近的记录(这将识别键:值对),并且您可以在减少的行集上应用 CROSS APPLY .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM