SQL 服务器 - LEFT JOIN 公共 属性 上的两个 JSON 对象

SQL Server - LEFT JOIN two JSON objects on a common property

我有一个 table,其中有一列包含 JSON 对象的架构(键、类型),另一个 table 包含一列,其中包含由该对象描述的实例架构。

对象实例可能缺少某些 JSON 架构属性,因此我想显示 NULL 作为该键的值。

例如,具有架构

[
        {"property": "label", "type": "string"},
        {"property": "id", "type": "number"}
]

和对象实例

'{"label__": "undefined label", "id": 111}

我想将 JSON 转换为 Key/Value 对的垂直 table(JKey 列仅供参考 - 另外,如您所见,“label__" 键及其值丢失,因为模式优先):

FProp   FType       JKey    JVal
---------------------------------
id      number      id      111
label   string      null    null

下面是我创建的 SQL,左连接模式与值,但它似乎不起作用。它仅输出与 属性 名称匹配的行。

DECLARE @schema NVARCHAR(MAX) = '
    {
        "fields": [
            {"property": "label", "type": "string"},
            {"property": "id", "type": "number"}
        ]
    }
';
WITH JsonSchemas AS (
    SELECT 1 AS SChemaId, @schema AS JSNDef
),
FieldsJsonValues AS (
  SELECT 1 AS FieldInstanceId, 1 as SchemaId,
 '{"label": "some label", "id": 1}' AS Val
  UNION ALL
  SELECT 2 , 1, '{"label__": "undefined label", "id": 2}'
),
SchemasTable AS (
SELECT S.SchemaId, JField.FProp, JField.FType
FROM JsonSchemas S
CROSS APPLY OPENJSON (S.JSNDef, '$.fields') AS JFieldsArr
CROSS APPLY OPENJSON (JFieldsArr.Value)
WITH
(
    FProp NVARCHAR(20) N'$.property',
    FType NVARCHAR(MAX) N'$.type'
) AS JField
),
FieldsValues AS (
    SELECT V.FieldInstanceId, V.SchemaId, KVPValues.[key] AS JKey,
 KVPValues.Value as JVal
    FROM FieldsJsonValues V
    CROSS APPLY OPENJSON (V.Val) KVPValues
)
SELECT ST.*, FV.FieldInstanceId, FV.JKey, FV.JVal
FROM SchemasTable ST
LEFT JOIN FieldsValues FV
ON ST.FProp = FV.JKey AND FV.SchemaId = ST.SChemaId
ORDER BY FieldInstanceId

我错过了什么?

将 LEFT JOIN 更改为 RIGHT JOIN 显示了正确的行数,但显然它将模式属性输出为 NULL。

SQL Fiddle here.

我认为您在 SchemasTable CTE 中需要一个额外的 LEFT JOIN

DECLARE @schema NVARCHAR(MAX) = '
    {
        "fields": [
            {"property": "label", "type": "string"},
            {"property": "id", "type": "number"}
        ]
    }
';

WITH JsonSchemas AS (
   SELECT 1 AS SChemaId, @schema AS JSNDef
),
FieldsJsonValues AS (
   SELECT 1 AS FieldInstanceId, 1 AS SchemaId, '{"label": "some label", "id": 1}' AS Val
   UNION ALL
   SELECT 2 , 1, '{"label__": "undefined label", "id": 2}'
),
SchemasTable AS (
   SELECT S.SchemaId, FV.FieldInstanceId, JField.FProp, JField.FType
   FROM JsonSchemas S
   CROSS APPLY OPENJSON (S.JSNDef, '$.fields') WITH (
      FProp NVARCHAR(20) N'$.property',
      FType NVARCHAR(MAX) N'$.type'
   ) AS JField
   LEFT JOIN FieldsJsonValues FV ON S.SchemaId = FV.SchemaId
),
FieldsValues AS (
   SELECT V.FieldInstanceId, V.SchemaId, KVPValues.[key] AS JKey, KVPValues.Value as JVal
   FROM FieldsJsonValues V
   CROSS APPLY OPENJSON (V.Val) KVPValues
)
SELECT ST.FProp, ST.FType, FV.JKey, FV.JVal
FROM SchemasTable ST
LEFT JOIN FieldsValues FV ON ST.SChemaId = FV.SchemaId AND ST.FieldInstanceId = FV.FieldInstanceId AND ST.FProp = FV.JKey
ORDER BY ST.FieldInstanceId

结果:

FProp FType JKey JVal
label string label some
id number id 1
id number id 2
label string