如何使用 like 语句检查 where 子句中 json 数组的每一项

How to I check each item of a json array within the where clause using a like statement

我正在为我的应用程序中的搜索字段创建一个查询。该查询使用 "like" 关键字来检查记录中的各种字段。其中一个字段是未命名的 ([{}, {}]) json 数组。数组中的字段全部匹配。我希望能够在不使用索引的情况下检查数组的每个 "Value" 属性,即“$[0].value”。原因是数组的大小可能会有所不同。以下是数据示例:

[{
    "MappedFieldName": "Customer",
    "DataType": "string",
    "Value": "Mapco Express"
}, {
    "MappedFieldName": "Invoice Nbr",
    "DataType": "string",
    "Value": "31856174"
}, {
    "MappedFieldName": "Invoice Document Date",
    "DataType": "DateTime",
    "Value": "2018-12-25 00:00:00.000"
}, {
    "MappedFieldName": "Processing Date",
    "DataType": "DateTime",
    "Value": "2019-01-04 00:00:00.000"
}, {
    "MappedFieldName": "Vendor Name",
    "DataType": "string",
    "Value": "Bullseye"
}, {
    "MappedFieldName": "Account Nbr",
    "DataType": "string",
    "Value": "0048219"
}, {
    "MappedFieldName": "Location #",
    "DataType": "string",
    "Value": "7520"
}, {
    "MappedFieldName": "Amount Invoiced",
    "DataType": "decimal",
    "Value": "3580.43"
}, {
    "MappedFieldName": "Amount Processed",
    "DataType": "decimal",
    "Value": "3580.43"
}, {
    "MappedFieldName": "Invoice Start Date",
    "DataType": "DateTime",
    "Value": "2018-04-01 00:00:00.000"
}, {
    "MappedFieldName": "Invoice End Date",
    "DataType": "DateTime",
    "Value": "2018-04-01 00:00:00.000"
}]

SELECT *
FROM [dbo].[Invoice]
WHERE JSON_VALUE(InvoiceData, '$.Value') like '%' + @searchText + '%'

此查询无效,因为我没有指定索引,即“$[0].Value”。

我明白了。我首先在搜索文本过滤器的记录的 json 字段上使用 OPENJSON,以获取找到文本的 json 数组部分的索引。接下来我使用索引where 子句标识要查找的数组索引。处理这个的代码如下。这将 return 在记录 json 数组中找到搜索文本的所有记录。

declare @searchText varchar(200) = '004'
declare @searchIndex varchar(10)

SELECT @searchIndex = [key]
FROM OPENJSON((SELECT InvoiceData FROM [dbo].[Invoice])) where Json_Value(value, '$.Value') like '%' + @searchText + '%'

SELECT *
    FROM [dbo].[Invoice]
    WHERE JSON_VALUE(InvoiceData, '$[' + @searchIndex +'].Value') like '%' + @searchText + '%'

这个答案可能会被简化。如果你有一个简单的答案,请随意post。

输入JSON是一个JSON对象的数组,具有固定结构(MappedFieldNameDataTypeValue键),所以另一种可能的方法是将 OPENJSON() 与显式架构一起使用到 return 一个 table 以及您在 WITH 子句中定义的列。使用这种方法,您可以过滤 invoices table and/or 从输入 JSON:

中获取更多信息

Table:

CREATE TABLE Invoices (
   InvoiceData nvarchar(max)
)
INSERT INTO Invoices 
   (InvoiceData)
VALUES
   (N'[{ "MappedFieldName": "Customer", "DataType": "string", "Value": "Mapco Express"}, { "MappedFieldName": "Invoice Nbr", "DataType": "string", "Value": "31856174"}, { "MappedFieldName": "Invoice Document Date", "DataType": "DateTime", "Value": "2018-12-25 00:00:00.000"}, { "MappedFieldName": "Processing Date", "DataType": "DateTime", "Value": "2019-01-04 00:00:00.000"}, { "MappedFieldName": "Vendor Name", "DataType": "string", "Value": "Bullseye"}, { "MappedFieldName": "Account Nbr", "DataType": "string", "Value": "0048219"}, { "MappedFieldName": "Location #", "DataType": "string", "Value": "7520"}, { "MappedFieldName": "Amount Invoiced", "DataType": "decimal", "Value": "3580.43"}, { "MappedFieldName": "Amount Processed", "DataType": "decimal", "Value": "3580.43"}, { "MappedFieldName": "Invoice Start Date", "DataType": "DateTime", "Value": "2018-04-01 00:00:00.000"}, { "MappedFieldName": "Invoice End Date", "DataType": "DateTime", "Value": "2018-04-01 00:00:00.000"}]')

声明:

DECLARE @search nvarchar(max) = '004'
SELECT 
   i.*,
   -- You may include the keys and values from the input JSON:
   j.*
FROM Invoices i
CROSS APPLY OPENJSON(i.InvoiceData) WITH (
   -- You may define only the columns, that you need here:
   [MappedFieldName] nvarchar(100) '$.MappedFieldName',
   [DataType] nvarchar(20) '$.DataType',
   [Value] nvarchar(100) '$.Value' 
) j
WHERE j.[Value] LIKE CONCAT('%', @search, '%')

查询可以简单地写成如下。当相应的 JSON 列中有一个或多个匹配项时,它将 return 1 张发票:

SELECT *
FROM invoice
WHERE EXISTS (
    SELECT 1
    FROM OPENJSON(invoicedata)
    WITH (
        [Value] NVARCHAR(100) '$.Value'
    )
    WHERE [Value] LIKE '%' + '004' + '%'
)

Demo on db<>fiddle