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 文档来指导我:
更新
我能够使用“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。
我有 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 文档来指导我:
更新
我能够使用“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。