如何查询带有键值对的 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
    )
);

db<>fiddle

YMMV 关于哪个解决方案更快。