我一直在尽可能多地阅读相同问题的问题和答案,但我想我的问题需要更具创造性的方法。
所以我在这里有一个JSON字符串:
declare @json nvarchar(max) =
'{
"propertyObjects": [{
"propertyID": 1
, "title": "foo"
, "class": ""
, "typeid": 150
, "value": "bar"
, "children": [{}]
}, {
"propertyID": 2
, "title": "foo"
, "class": ""
, "typeid": 128
, "value": "bar"
, "children": [{}]
}, {
"propertyID": 3
, "title": "foo"
, "class": ""
, "typeid": 128
, "value": "bar"
, "children": [{
"propertyID": 4
, "title": "foo"
, "class": ""
, "typeid": 128
, "value": "bar"
, "children": [{}]
}, {
"propertyID": 5
, "title": "foo"
, "class": ""
, "typeid": 128
, "value": "bar"
, "children": [{}]
}, {
"propertyID": 6
, "title": "foo"
, "class": ""
, "typeid": 128
, "value": "bar"
, "children": [{
"propertyID": 7
, "title": "foo"
, "class": ""
, "typeid": 128
, "value": "bar"
, "children": [{
"propertyID": 8
, "title": "foo"
, "class": ""
, "typeid": 128
, "value": "bar"
, "children": [{}]
}]
}]
}]
}]
}'
乍一看是疯了,但想到这一点:我想要的是在我们为每个对象指定父ID时在表中列出这些对象,因此对象4具有ID为3的父对象,对象3本身为父0,因为它基本上位于顶部水平。
到目前为止,我尝试了一些方法,如公用表表达式来进行递归调用,但我失败了:
;with cte
as
(
-- anchor member definition
select p.propertyID
, 0 as parentID
, p.title
, p.typeid
, p.[value]
, p.children
from openjson(@json, '$.propertyObjects')
with (
propertyID int
, title nvarchar(100)
, typeid int
, [value] nvarchar(1000)
, children nvarchar(max) as JSON
) as p
UNION ALL
-- recursive member definition
select 0 as propertyID
, 0 as parentID
, '' as title
, 0 typeid
, '' as [value]
, '' as children
/** child should be bound to parent **/
)
select * from cte
在这里,我失败了,我不知道如何通过孩子递归地找到对象。另外,我不知道如何指定每个孩子的parentID!
propertyID parentID title typeid value children
----------------------------------------------------------------------------
1 0 foo 150 bar [{}]
2 0 foo 128 bar [{}]
3 0 foo 128 bar [{ "propertyID" : 4 ...
0 0 0
我也尝试过使用交叉申请:
select *
from
openjson(@json, '$.propertyObjects')
with (
propertyID int
, title nvarchar(100)
, typeid int
, [value] nvarchar(1000)
, children nvarchar(max) as JSON
) as p
cross apply
openjson(p.children)
with (
propertyID int
, title nvarchar(100)
, typeid int
, [value] nvarchar(1000)
, children nvarchar(max) as JSON
) as r
但不是偶然,我不知道这些孩子在JSON字符串中的深度。此外,交叉应用的结果将追加列而不是导致结果中存在巨型表的行,并且在这种方法中我甚至不能考虑指定parentID。
这完全是一个失败,关于如何让所有孩子成行的任何想法?
所需表格
propertyID parentID title typeid value
--------------------------------------------------
1 0 foo 150 bar
2 0 foo 128 bar
3 0 foo 128 bar
4 3 foo 128 bar
5 3 foo 128 bar
6 3 foo 128 bar
7 6 foo 128 bar
8 7 foo 128 bar
答案 0 :(得分:1)
您实际上非常接近-您只需将CROSS APPLY
与OPENJSON
一起使用:
with cte as (
select
p.propertyID,
0 as parentID,
p.title,
p.typeid,
p.[value],
p.children
from openjson(@json, '$.propertyObjects') with (
propertyID int,
title nvarchar(100),
typeid int,
[value] nvarchar(1000),
children nvarchar(max) as json
) as p
union all
select
p.propertyID,
c.propertyID,
p.title,
p.typeid,
p.[value],
p.children
from cte as c
cross apply openjson(c.children) with (
propertyID int,
title nvarchar(100),
typeid int,
[value] nvarchar(1000),
children nvarchar(max) as json
) as p
where
c.children <> '[{}]'
)
select
c.propertyID,
c.parentID,
c.title,
c.typeid,
c.value
from cte as c
答案 1 :(得分:0)
就我在工作中学习这个主题而言,这几乎不可能潜入未知的嵌套JSON级别,同时性能不佳。
我所做的是避免嵌套级别,我在一个级别创建了JSON字符串,只是返回其中包含键值对的所有对象,并且还更改了数据库中的数据模型。
拥有有效且合理的数据结构比拥有复杂编码技能更为重要。