如何查询带有键值对的 table 和 JSON 列以匹配所有键和值
How to query a table with JSON column with key-value pairs to match all keys and values
假设我有一个 Image
table,在 JSON 中有一个元列:
Id
Meta
1
{ "size": 80, "effect": "blur" }
2
{ "size": 200, "optimize": true }
3
{ "color": "#abcdef", "ext": ".jpg" }
我有一个 table 类型的动态参数
Key
Value
size
200
optimize
true
我应该如何编写查询来过滤 Meta 列的键值对与参数 table 中的所有值匹配的行?
SELECT Id
FROM Image
WHERE (
--?? all keys and values matched the param table
)
这是一种 relational division (with remainder) 问题,同时具有粉碎 JSON 的额外扭曲。
这类问题有多种解法。一种常见的解决方案是 LEFT JOIN
股息的除数,将其分组并检查任何 non-matches:
DECLARE @tmp TABLE (
"Key" NVARCHAR(8) COLLATE Latin1_General_BIN2,
"Value" NVARCHAR(4) COLLATE Latin1_General_BIN2
);
INSERT INTO @tmp
("Key", "Value")
VALUES
('size', '200'),
('optimize', 'true');
SELECT *
FROM Image i
WHERE EXISTS (SELECT 1
FROM @tmp t
LEFT JOIN OPENJSON(i.Meta) j ON t.[Key] = j.[key] AND t.Value = j.value
HAVING COUNT(j.value) = COUNT(*) -- all match
);
另一个解决方案是使用双 NOT EXISTS
:有 no key/value 输入对 not 有一场比赛
DECLARE @tmp TABLE (
"Key" NVARCHAR(8) COLLATE Latin1_General_BIN2,
"Value" NVARCHAR(4) COLLATE Latin1_General_BIN2
);
INSERT INTO @tmp
("Key", "Value")
VALUES
('size', '200'),
('optimize', 'true');
SELECT *
FROM Image i
WHERE NOT EXISTS (SELECT 1
FROM @tmp t
WHERE NOT EXISTS (SELECT 1
FROM OPENJSON(i.Meta) j
WHERE t.[Key] = j.[key] AND t.Value = j.value
)
);
YMMV 关于哪个解决方案更快。
假设我有一个 Image
table,在 JSON 中有一个元列:
Id | Meta |
---|---|
1 | { "size": 80, "effect": "blur" } |
2 | { "size": 200, "optimize": true } |
3 | { "color": "#abcdef", "ext": ".jpg" } |
我有一个 table 类型的动态参数
Key | Value |
---|---|
size | 200 |
optimize | true |
我应该如何编写查询来过滤 Meta 列的键值对与参数 table 中的所有值匹配的行?
SELECT Id
FROM Image
WHERE (
--?? all keys and values matched the param table
)
这是一种 relational division (with remainder) 问题,同时具有粉碎 JSON 的额外扭曲。
这类问题有多种解法。一种常见的解决方案是 LEFT JOIN
股息的除数,将其分组并检查任何 non-matches:
DECLARE @tmp TABLE (
"Key" NVARCHAR(8) COLLATE Latin1_General_BIN2,
"Value" NVARCHAR(4) COLLATE Latin1_General_BIN2
);
INSERT INTO @tmp
("Key", "Value")
VALUES
('size', '200'),
('optimize', 'true');
SELECT *
FROM Image i
WHERE EXISTS (SELECT 1
FROM @tmp t
LEFT JOIN OPENJSON(i.Meta) j ON t.[Key] = j.[key] AND t.Value = j.value
HAVING COUNT(j.value) = COUNT(*) -- all match
);
另一个解决方案是使用双 NOT EXISTS
:有 no key/value 输入对 not 有一场比赛
DECLARE @tmp TABLE (
"Key" NVARCHAR(8) COLLATE Latin1_General_BIN2,
"Value" NVARCHAR(4) COLLATE Latin1_General_BIN2
);
INSERT INTO @tmp
("Key", "Value")
VALUES
('size', '200'),
('optimize', 'true');
SELECT *
FROM Image i
WHERE NOT EXISTS (SELECT 1
FROM @tmp t
WHERE NOT EXISTS (SELECT 1
FROM OPENJSON(i.Meta) j
WHERE t.[Key] = j.[key] AND t.Value = j.value
)
);
YMMV 关于哪个解决方案更快。