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
我有一个 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 |