对 JSON 数据的 SQL LIKE 查询

Posted

技术标签:

【中文标题】对 JSON 数据的 SQL LIKE 查询【英文标题】:SQL LIKE query on JSON data 【发布时间】:2019-11-29 19:41:23 【问题描述】:

我将 JSON 数据(无架构)存储在 SQL Server 列中,需要对其运行搜索查询。

例如(不是实际数据)

[
 
   "Color":"Red",
   "Make":"Mercedes-Benz"  
 ,
 
   "Color":"Green",
   "Make":"Ford"  
 ,
]

SQL Server 2017 具有 JSON_XXXX 方法,但它们适用于已知架构。在我的例子中,对象的模式没有精确定义并且可能会改变。

目前要搜索列,例如找到 Make=Mercedes-Benz。我正在使用搜索短语“%\"Make\":\"Mercedes-Benz\"%"。如果使用确切的品牌名称,这非常有效。我希望用户也能够使用部分名称进行搜索,例如只需输入“Benz”或“merc”。

是否可以使用适合我的通配符构建 SQL 查询?还有其他选择吗?

【问题讨论】:

您可以在不定义数据的情况下使用OPENJSON,但是从中获取有用的数据是很困难的。样本数据和预期结果会很好 这是非结构化数据的问题。那是你唯一的问题。如果你解决了这个问题,所有其他问题都会消失。接受 JSON 的 RDMS 无法解决这个问题,MongoDB 之类的东西也无法解决。 【参考方案1】:

一种可能的方法是将OPENJSON 与默认架构一起使用两次。使用默认架构,OPENJSONreturns 包含列 keyvaluetype 的表,您可以将它们用于您的 WHERE 子句。

表:

CREATE TABLE #Data (
   Json nvarchar(max)
)
INSERT INTO #Data
   (Json)
VALUES
   (N'[
 
   "Color":"Red",
   "Make":"Mercedes-Benz"  
 ,
 
   "Color":"Green",
   "Make":"Ford",
   "Year": 2000
 
]')

声明:

SELECT 
   j1.[value]
   -- or other columns 
FROM #Data d
CROSS APPLY OPENJSON(d.Json) j1
CROSS APPLY OPENJSON(j1.[value]) j2
WHERE 
   j2.[key] LIKE '%Make%' AND
   j2.[value] LIKE '%Benz%'

输出:

--------------------------
value
--------------------------

   "Color":"Red",
   "Make":"Mercedes-Benz"  
 

【讨论】:

【参考方案2】:

你可以用 ',' 分割 json 并像这样搜索:

WHERE EXISTS (SELECT *  
            FROM STRING_SPLIT(json_data, ',')  
           WHERE value LIKE  '%\"Make\":%'
             AND value LIKE  '%Benz%' 
           );

【讨论】:

【参考方案3】:

如果您碰巧运行的是不支持内置 JSON 函数(如 OPENJSON())的旧版本 SQL Server,则可以使用类似于以下的 SQL。

您可以在http://sqlfiddle.com/#!18/dd7a5 尝试测试此 SQL

注意:此 SQL 假定您正在搜索的键仅在每个记录/JSON 对象文字中出现一次(换句话说,您仅在每个记录/数据库行中存储具有唯一键的 JSON 对象文字)。另请注意,SELECT 查询是丑陋的,但它有效。

/* see http://sqlfiddle.com/#!18/dd7a5 to test this online*/
/* setup a test data table schema */
CREATE TABLE myData (
   [id] [int] IDENTITY(1,1) NOT NULL,
   [jsonData] nvarchar(4000)
  CONSTRAINT [PK_id] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)
);

/* Insert some test data */
INSERT INTO myData
   (jsonData)
VALUES
   ('
   "Color":"Red",
   "Make":"Mercedes-Benz"
 ');
 
 INSERT INTO myData
   (jsonData)
VALUES
   (
   '
   "Color":"White",
   "Make":"Toyota",
   "Model":"Prius",
   "VIN":"123454321"
 ');

INSERT INTO myData
   (jsonData)
VALUES
   (
   '
   "Color":"White",
   "Make":"Mercedes-Benz",
   "Year": 2009
 ');
 
 INSERT INTO myData
   (jsonData)
VALUES
   (
   '
   "Type":"Toy",
   "Color":"White",
   "Make":"Toyota",
   "Model":"Prius",
   "VIN":"99993333"
 ');

/* This select statement searches the 'Make' keys, within the jsonData records, with values LIKE '%oyo%'. This statement will return records such as 'Toyota' as the Make value. */
SELECT id, SUBSTRING(
        jsonData
        ,CHARINDEX('"Make":', jsonData) + LEN('"Make":')
        ,CHARINDEX(',', jsonData, CHARINDEX('"Make":', jsonData) + LEN('"Make":')) - CHARINDEX('"Make":', jsonData) - LEN('"Make":')
        ) as CarMake FROM myData
WHERE 
SUBSTRING(
        jsonData
        ,CHARINDEX('"Make":"', jsonData) + LEN('"Make":"')
        ,CHARINDEX('"', jsonData, CHARINDEX('"Make":"', jsonData) + LEN('"Make":"')) - CHARINDEX('"Make":"', jsonData) - LEN('"Make":"')
        ) LIKE '%oyo%'

【讨论】:

以上是关于对 JSON 数据的 SQL LIKE 查询的主要内容,如果未能解决你的问题,请参考以下文章

MySQL查询like语句查询

sql模糊查询

sql 对同一字段进行模糊查询时如何将两个条件写入一个like中

sql like 通配符 模糊查询技巧及特殊字符

Hbase能模糊查询吗,类似like

Sql优化-多like模糊查询及根据时间排序