Sql server 带有两个数组的对象上的OPENJSON
我在一列中有以下json:Sql server 带有两个数组的对象上的OPENJSON,sql-server,tsql,Sql Server,Tsql,我在一列中有以下json: { "fields":[ { "field":"modelName", "value":"abc123" }, { "field":"displayName", "value":"ABC 123" }, { "field":"order", "value":5 } ], "
{
"fields":[
{
"field":"modelName",
"value":"abc123"
},
{
"field":"displayName",
"value":"ABC 123"
},
{
"field":"order",
"value":5
}
],
"variables":[
{
"varId":4,
"oldValue":100,
"newValue":"150"
},
{
"varId":5,
"oldValue":"abc",
"newValue":"def"
}
]
}
我想把这些信息引向如下:
Id Field Value VarId oldValue newValue
2 modelName abc123 null null null
2 displayName ABC 123 null null null
2 order 5 null null null
2 null null 4 100 150
2 null null 5 abc def
这样我就可以遍历结果集,然后进行空检查以查看它是什么类型
我目前有以下声明:
select Id, Fields.Field, Fields.Value, Variables.VarId, Variables.OldValue, Variables.NewValue from Product
cross apply openjson( data, '$.fields') with (Field varchar(50) '$.field', Value varchar(50) '$.value') AS Fields
cross apply openjson( data, '$.variables') with (VarId int '$.varId', OldValue varchar(50) '$.oldValue', NewValue varchar(50) '$.newValue') AS Variables
但它给了我以下输出:
正如你所看到的,一切都是重复的。有可能得到我想要的输出吗
谢谢您需要进行两次单独的解析。这使用了一个
完全外部联接
和一个(公认的)dumbON
子句。您还可以使用UNION ALL
和NULL
对集合中没有列的值执行以下操作:
CREATE TABLE dbo.Product (ID int,
[data] nvarchar(MAX));
DECLARE @JSON nvarchar(MAX) = N'{
"fields":[
{
"field":"modelName",
"value":"abc123"
},
{
"field":"displayName",
"value":"ABC 123"
},
{
"field":"order",
"value":5
}
],
"variables":[
{
"varId":4,
"oldValue":100,
"newValue":"150"
},
{
"varId":5,
"oldValue":"abc",
"newValue":"def"
}
]
}';
INSERT INTO dbo.Product (ID,
[data])
VALUES(2,@JSON);
GO
WITH Fields AS(
SELECT P.Id,
F.Field,
F.Value,
FROM Product P
CROSS APPLY OPENJSON(data, '$.fields')
WITH (Field varchar(50) '$.field',
[Value] varchar(50) '$.value') F),
Variables AS(
SELECT P.Id,
V.VarId,
V.OldValue,
V.NewValue
FROM Product P
CROSS APPLY OPENJSON(data, '$.variables')
WITH (VarId int '$.varId',
OldValue varchar(50) '$.oldValue',
NewValue varchar(50) '$.newValue') V)
SELECT ISNULL(F.ID,V.ID) AS ID,
F.Field,
F.[Value],
V.VarId,
V.OldValue,
V.NewValue
FROM Fields F
FULL OUTER JOIN Variables V ON 1 = 2; --Dumb ON clause is Dumb
您将需要进行两次单独的解析。这使用了一个
完全外部联接
和一个(公认的)dumbON
子句。您还可以使用UNION ALL
和NULL
对集合中没有列的值执行以下操作:
CREATE TABLE dbo.Product (ID int,
[data] nvarchar(MAX));
DECLARE @JSON nvarchar(MAX) = N'{
"fields":[
{
"field":"modelName",
"value":"abc123"
},
{
"field":"displayName",
"value":"ABC 123"
},
{
"field":"order",
"value":5
}
],
"variables":[
{
"varId":4,
"oldValue":100,
"newValue":"150"
},
{
"varId":5,
"oldValue":"abc",
"newValue":"def"
}
]
}';
INSERT INTO dbo.Product (ID,
[data])
VALUES(2,@JSON);
GO
WITH Fields AS(
SELECT P.Id,
F.Field,
F.Value,
FROM Product P
CROSS APPLY OPENJSON(data, '$.fields')
WITH (Field varchar(50) '$.field',
[Value] varchar(50) '$.value') F),
Variables AS(
SELECT P.Id,
V.VarId,
V.OldValue,
V.NewValue
FROM Product P
CROSS APPLY OPENJSON(data, '$.variables')
WITH (VarId int '$.varId',
OldValue varchar(50) '$.oldValue',
NewValue varchar(50) '$.newValue') V)
SELECT ISNULL(F.ID,V.ID) AS ID,
F.Field,
F.[Value],
V.VarId,
V.OldValue,
V.NewValue
FROM Fields F
FULL OUTER JOIN Variables V ON 1 = 2; --Dumb ON clause is Dumb
这只是另一种可能的方法(感谢@Larnu提供的测试数据)。当然,您需要分别解析
字段
和变量
部分,但您可以将OPENJSON()
与一个显式模式(with
子句)结合使用:
表:
CREATE TABLE Product (
ID int,
[data] nvarchar(MAX)
);
DECLARE @json nvarchar(MAX) = N'{
"fields":[
{
"field":"modelName",
"value":"abc123"
},
{
"field":"displayName",
"value":"ABC 123"
},
{
"field":"order",
"value":5
}
],
"variables":[
{
"varId":4,
"oldValue":100,
"newValue":"150"
},
{
"varId":5,
"oldValue":"abc",
"newValue":"def"
}
]
}';
INSERT INTO Product (ID, [data])
VALUES
(1, @json),
(2, @json),
(3, @json)
声明:
SELECT p.ID, j.*
FROM Product p
CROSS APPLY (
SELECT *
FROM OPENJSON (p.data, '$.fields') WITH (
field varchar(100) '$.field',
value varchar(100) '$.value',
varId int '$.varId',
oldValue varchar(100) '$.oldValue',
newValue varchar(100) '$.newValue'
)
UNION ALL
SELECT *
FROM OPENJSON (p.data, '$.variables') WITH (
field varchar(100) '$.field',
value varchar(100) '$.value',
varId int '$.varId',
oldValue varchar(100) '$.oldValue',
newValue varchar(100) '$.newValue'
)
) j
-- Additional WHERE clause
--WHERE p.ID = 2
这只是另一种可能的方法(感谢@Larnu提供的测试数据)。当然,您需要分别解析
字段
和变量
部分,但您可以将OPENJSON()
与一个显式模式(with
子句)结合使用:
表:
CREATE TABLE Product (
ID int,
[data] nvarchar(MAX)
);
DECLARE @json nvarchar(MAX) = N'{
"fields":[
{
"field":"modelName",
"value":"abc123"
},
{
"field":"displayName",
"value":"ABC 123"
},
{
"field":"order",
"value":5
}
],
"variables":[
{
"varId":4,
"oldValue":100,
"newValue":"150"
},
{
"varId":5,
"oldValue":"abc",
"newValue":"def"
}
]
}';
INSERT INTO Product (ID, [data])
VALUES
(1, @json),
(2, @json),
(3, @json)
声明:
SELECT p.ID, j.*
FROM Product p
CROSS APPLY (
SELECT *
FROM OPENJSON (p.data, '$.fields') WITH (
field varchar(100) '$.field',
value varchar(100) '$.value',
varId int '$.varId',
oldValue varchar(100) '$.oldValue',
newValue varchar(100) '$.newValue'
)
UNION ALL
SELECT *
FROM OPENJSON (p.data, '$.variables') WITH (
field varchar(100) '$.field',
value varchar(100) '$.value',
varId int '$.varId',
oldValue varchar(100) '$.oldValue',
newValue varchar(100) '$.newValue'
)
) j
-- Additional WHERE clause
--WHERE p.ID = 2
太好了,没想到会这么快得到答复,谢谢!但是有一个问题,如果我想过滤P.Id,那么
where
子句会去哪里?我试着将它放在单独的语法分析中,但无法获得正确的语法。我不确定是否把它放在最后一个select语句中。“SQL是否足够聪明,可以只抓取我想要的,或者它会抓取每个解析器中的所有内容,然后过滤掉它呢?我会,但它会在CTE中,”阿德林格说。语法应该是,其中P.ID=1
<代码>其中是SQL的基础之一,因此如果您不熟悉它,我建议您阅读一下。非常好,没想到会有这么快的答案,谢谢!但是有一个问题,如果我想过滤P.Id,那么where
子句会去哪里?我试着将它放在单独的语法分析中,但无法获得正确的语法。我不确定是否把它放在最后一个select语句中。“SQL是否足够聪明,可以只抓取我想要的,或者它会抓取每个解析器中的所有内容,然后过滤掉它呢?我会,但它会在CTE中,”阿德林格说。语法应该是,其中P.ID=1
<代码>其中是SQL的基础之一,因此如果您不熟悉它,我建议您阅读一下。