使用LIKE和JSON对象进行部分搜索

时间:2019-01-04 19:17:32

标签: sql sql-server sql-server-2017

我正在尝试在WHERE过滤器的JSON子句中使用部分搜索。我正在传递一个,分隔字符串,并希望在where语句中将其分开。

例如:

示例表:

create table NewTable
(
   Id int identity(1,1) primary key,
   SomeObject varchar(20),
   SomeText varchar(20)
)

INSERT INTO NewTable(SomeObject, SomeText)values ('hello', 'test1')
INSERT INTO NewTable(SomeObject, SomeText)values ('yellow', 'test2')
INSERT INTO NewTable(SomeObject, SomeText)values ('test1', 'test1')

以下是通过的过滤器:

DECLARE @Filter NVARCHAR(MAX)

SET @Filter=N'{
  "SomeObject": "ello,yel"
}'

我正在尝试从具有'%ello%''%yel%'的表中选择所有内容

select * from newtable pm
where 
(pm.SomeObject IS NULL AND JSON_VALUE(@Filter,N'$.SomeObject') IS NULL OR pm.SomeObject LIKE '%' + (select value from string_split(ISNULL(JSON_VALUE(@Filter,N'$.SomeObject'),pm.SomeObject), ',')) + '%')

此查询部分起作用。我有许多实例,subquery将返回多于1行。我可以切换为使用IN子句,但无法执行部分搜索。有关如何解决此问题的任何建议?

编辑:

基于上述过滤器,输出应返回在ello列中具有yelSomeObject的所有行。因此,在此示例中,应返回第1行和第2行。

3 个答案:

答案 0 :(得分:1)

一种方法是使用OPENJSON解析JSON,然后使用STRING_SPLIT分隔定界列表:

DECLARE @Filter nvarchar(MAX);

SET @Filter=N'{
  "SomeObject": "ello,yel"
}';
WITH CTE AS(
    SELECT NT.Id,
           NT.SomeObject,
           NT.SomeText,
           ROW_NUMBER() OVER (PARTITION BY NT.ID ORDER BY SS.[Value]) AS RN
    FROM dbo.NewTable NT
        CROSS APPLY OPENJSON(@Filter) OJ
        CROSS APPLY STRING_SPLIT(OJ.[value], ',') SS
    WHERE NT.SomeObject LIKE '%' + SS.[value] + '%')
SELECT Id,
       SomeObject,
       SomeText
FROM CTE
WHERE RN = 1;

但是,由于行可以多次匹配('Yellow'包含字符串'yel''ello'),因此您还需要CTE以确保每个{{1 }}返回。

答案 1 :(得分:1)

也许这会像hello这样的串联正则表达式中的每个字符串一样匹配%[hello]%[yellow]%

  select * from newtable pm
    where 
   (pm.SomeObject IS NULL AND 
  JSON_VALUE(@Filter,N'$.SomeObject') IS NULL 
    OR pm.SomeObject  LIKE '%[' + select 
  REPLACE
    (JSON_VALUE(@Filter,N'$.SomeObject')
            ,',',']%['  ) + ']%' 
     )

答案 2 :(得分:1)

如果我对您的理解正确,则可以尝试以下操作:

-- Table
CREATE TABLE NewTable
(
   Id int identity(1,1) primary key,
   SomeObject varchar(20),
   SomeText varchar(20)
)
INSERT INTO NewTable(SomeObject, SomeText) VALUES ('hello', 'test1')
INSERT INTO NewTable(SomeObject, SomeText) VALUES ('yellow', 'test2')
INSERT INTO NewTable(SomeObject, SomeText) VALUES ('test1', 'test1')

-- JSON
DECLARE @Filter nvarchar(MAX)
SET @Filter = N'{
  "SomeObject": "ello,yel"
}'

-- Statement
SELECT pm.*
FROM NewTable pm
WHERE 
   -- 1. @Filter is null
   (ISJSON(@Filter) IS NULL) OR
   -- 2. $.SomeObject is empty text, @Filter = N'{"SomeObject": ""}'
   (JSON_VALUE(@Filter, '$.SomeObject') = N'') OR
   (JSON_VALUE(@Filter, '$.SomeObject') IS NULL) OR
   -- 3. Filter exists
   (
      (ISJSON(@Filter) IS NOT NULL) AND
      (JSON_VALUE(@Filter, '$.SomeObject') <> N'') AND
      (JSON_VALUE(@Filter, '$.SomeObject') IS NOT NULL) AND
      EXISTS (
         SELECT * 
         FROM STRING_SPLIT(JSON_VALUE(@Filter, '$.SomeObject'), ',') 
         WHERE pm.SomeObject LIKE CONCAT('%', [Value], '%')
      )
   )