Find Ancestry From JSONHow to remove object from json array?Can I find all JSON scalars in PostgreSQL 9.3?JSON format for time-loggingCan SQL Server 2016 extract node names from JSON?MySQL: Return JSON from a standard SQL QueryPostgres JSON output using specific column as JSON keyExtract JSON array of numbers from JSON array of objectsMust numeric JSON keys be quoted?update json value to nullSelect JSON elements from nested documnet
How to pass a regex when finding a directory path in bash?
Proof that shortest path with negative cycles is NP hard
How do I write "Show, Don't Tell" as a person with Asperger Syndrome?
How can you travel on a trans-Siberian train when it is fully booked?
Will TSA allow me to carry a Continuous Positive Airway Pressure (CPAP)/sleep apnea device?
4*4*4 Rubiks cube Top Layer Issue
PL/SQL function to receive a number and return its binary format
How to retract the pitched idea from employer?
Can a user sell my software (MIT license) without modification?
What's the correct term for a waitress in the Middle Ages?
Secure offsite backup, even in the case of hacker root access
Etymology of 'calcit(r)are'?
Where does this pattern of naming products come from?
Traffic law UK, pedestrians
Should I "tell" my exposition or give it through dialogue?
Do the English have an ancient (obsolete) verb for the action of the book opening?
Company did not petition for visa in a timely manner. Is asking me to work from overseas, but wants me to take a paycut
Select items in a list that contain criteria #2
Did thousands of women die every year due to illegal abortions before Roe v. Wade?
Why does the Schrödinger equation work so well for the Hydrogen atom despite the relativistic boundary at the nucleus?
Turing patterns
Do simulator games use a realistic trajectory to get into orbit?
2.8 is missing the Carve option in the Boolean Modifier
Are "living" organ banks practical?
Find Ancestry From JSON
How to remove object from json array?Can I find all JSON scalars in PostgreSQL 9.3?JSON format for time-loggingCan SQL Server 2016 extract node names from JSON?MySQL: Return JSON from a standard SQL QueryPostgres JSON output using specific column as JSON keyExtract JSON array of numbers from JSON array of objectsMust numeric JSON keys be quoted?update json value to nullSelect JSON elements from nested documnet
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I have a hierarchy that looks like this:

As JSON in TSQL it is this:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
This is just an example. The actual data could be any tree of indeterminate depth or breadth.
The documentation and all the examples I've found show top-down traversal. Every JSON path starts at the root node and navigates, by known node names, toward the desired node. I've found nothing about starting at an indeterminate depth within the hierarchy and working upward. I feel like I need something like transitive closure.
Given a name I would like to get the ancestry for that name. For example, given "Emma" the result will be "Emma / Chris / Amy". Given "Bill" the answer will be "Bill / Amy". The output format is unimportant; it can be JSON, a string or a resultset. The names are unique.
This is a learning exercise for myself. It's OK to change the original JSON representation to anything equivalent as long as it's still JSONy. A JSON_QUERY over an adjacency list representation of the hierarchy wouldn't achieve my goal.
sql-server t-sql json
This question has an open bounty worth +50
reputation from Michael Green ending ending at 2019-06-09 10:39:36Z">in 6 days.
One or more of the answers is exemplary and worthy of an additional bounty.
add a comment |
I have a hierarchy that looks like this:

As JSON in TSQL it is this:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
This is just an example. The actual data could be any tree of indeterminate depth or breadth.
The documentation and all the examples I've found show top-down traversal. Every JSON path starts at the root node and navigates, by known node names, toward the desired node. I've found nothing about starting at an indeterminate depth within the hierarchy and working upward. I feel like I need something like transitive closure.
Given a name I would like to get the ancestry for that name. For example, given "Emma" the result will be "Emma / Chris / Amy". Given "Bill" the answer will be "Bill / Amy". The output format is unimportant; it can be JSON, a string or a resultset. The names are unique.
This is a learning exercise for myself. It's OK to change the original JSON representation to anything equivalent as long as it's still JSONy. A JSON_QUERY over an adjacency list representation of the hierarchy wouldn't achieve my goal.
sql-server t-sql json
This question has an open bounty worth +50
reputation from Michael Green ending ending at 2019-06-09 10:39:36Z">in 6 days.
One or more of the answers is exemplary and worthy of an additional bounty.
add a comment |
I have a hierarchy that looks like this:

As JSON in TSQL it is this:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
This is just an example. The actual data could be any tree of indeterminate depth or breadth.
The documentation and all the examples I've found show top-down traversal. Every JSON path starts at the root node and navigates, by known node names, toward the desired node. I've found nothing about starting at an indeterminate depth within the hierarchy and working upward. I feel like I need something like transitive closure.
Given a name I would like to get the ancestry for that name. For example, given "Emma" the result will be "Emma / Chris / Amy". Given "Bill" the answer will be "Bill / Amy". The output format is unimportant; it can be JSON, a string or a resultset. The names are unique.
This is a learning exercise for myself. It's OK to change the original JSON representation to anything equivalent as long as it's still JSONy. A JSON_QUERY over an adjacency list representation of the hierarchy wouldn't achieve my goal.
sql-server t-sql json
I have a hierarchy that looks like this:

As JSON in TSQL it is this:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
This is just an example. The actual data could be any tree of indeterminate depth or breadth.
The documentation and all the examples I've found show top-down traversal. Every JSON path starts at the root node and navigates, by known node names, toward the desired node. I've found nothing about starting at an indeterminate depth within the hierarchy and working upward. I feel like I need something like transitive closure.
Given a name I would like to get the ancestry for that name. For example, given "Emma" the result will be "Emma / Chris / Amy". Given "Bill" the answer will be "Bill / Amy". The output format is unimportant; it can be JSON, a string or a resultset. The names are unique.
This is a learning exercise for myself. It's OK to change the original JSON representation to anything equivalent as long as it's still JSONy. A JSON_QUERY over an adjacency list representation of the hierarchy wouldn't achieve my goal.
sql-server t-sql json
sql-server t-sql json
edited May 28 at 9:53
Michael Green
asked May 28 at 6:57
Michael GreenMichael Green
15.1k83264
15.1k83264
This question has an open bounty worth +50
reputation from Michael Green ending ending at 2019-06-09 10:39:36Z">in 6 days.
One or more of the answers is exemplary and worthy of an additional bounty.
This question has an open bounty worth +50
reputation from Michael Green ending ending at 2019-06-09 10:39:36Z">in 6 days.
One or more of the answers is exemplary and worthy of an additional bounty.
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
This seems to me to be a pretty vanilla recursion query so long as you unwrap the JSON dynamically.
If HandyD will excuse some slight plagiarism...
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH hier ([Level], Parent, Person, staff) AS (
SELECT
1 AS [Level],
convert(nvarchar(255),'') AS Parent,
l1.person,
l1.staff
FROM OPENJSON(@Employees) WITH (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
UNION ALL
select
[Level]+1,
convert(nvarchar(255),h.Person) as Parent,
oj.person,
oj.staff
from hier h
outer apply openjson(h.staff) with (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) oj
where [Level] < 100 -- or relevant maxrecursion level
and oj.Person is not null
)
SELECT
[Level],
Parent,
Person
FROM hier
order by [Level];
Nice. The recursive approach allows for data changes. Can you think of a JSONy way of returning only the single path from Emma to Amy? I know this output forms an adjacency list and I could perform a recursive path walk upwards. I was hoping for something in the JSON itself, if you have a suggestion.
– Michael Green
May 28 at 12:47
@MichaelGreen - is this what you were looking for? dbfiddle.uk/…
– Peter Vandivier
May 28 at 13:44
@PeterVandivier Plagiarism excused :) I was trying to get the recursion working myself so it would handle N levels automatically but couldn't get it quite right
– HandyD
May 28 at 23:52
@PeterVandivier Yes, that's it. I had hoped there was a JSON path "get parent" operator but it seems there is not.
– Michael Green
May 29 at 4:43
add a comment |
You can use OPENJSON and a CTE to extract each person and their associated staff:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH Level1 AS (
SELECT 1 AS Level, NULL AS Parent, l1.person, l1.staff
FROM OPENJSON(@Employees)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
), Level2 AS (
SELECT 2 AS Level, l1.person AS Parent, l2.person, l2.staff
FROM Level1 l1
CROSS APPLY OPENJSON(l1.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l2
), Level3 AS (
SELECT 3 AS Level, l2.person AS Parent, l3.person, l3.staff
FROM Level2 l2
CROSS APPLY OPENJSON(l2.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l3
)
SELECT Level, Parent, Person FROM Level1
UNION
SELECT Level, Parent, Person FROM Level2
UNION
SELECT Level, Parent, Person FROM Level3
ORDER BY Level
Returns:
Level Parent Person
----------------------
1 NULL Amy
2 Amy Bill
2 Amy Chris
3 Chris Emma
3 Chris Dan
Thank you. Two questions 1) how would you return the just the Emma - Chris - Amy path without the other nodes? 2) if we added Frances, reporting to Emma, wouldn't this query have to be extended by another level?
– Michael Green
May 28 at 9:51
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "182"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f239180%2ffind-ancestry-from-json%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
This seems to me to be a pretty vanilla recursion query so long as you unwrap the JSON dynamically.
If HandyD will excuse some slight plagiarism...
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH hier ([Level], Parent, Person, staff) AS (
SELECT
1 AS [Level],
convert(nvarchar(255),'') AS Parent,
l1.person,
l1.staff
FROM OPENJSON(@Employees) WITH (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
UNION ALL
select
[Level]+1,
convert(nvarchar(255),h.Person) as Parent,
oj.person,
oj.staff
from hier h
outer apply openjson(h.staff) with (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) oj
where [Level] < 100 -- or relevant maxrecursion level
and oj.Person is not null
)
SELECT
[Level],
Parent,
Person
FROM hier
order by [Level];
Nice. The recursive approach allows for data changes. Can you think of a JSONy way of returning only the single path from Emma to Amy? I know this output forms an adjacency list and I could perform a recursive path walk upwards. I was hoping for something in the JSON itself, if you have a suggestion.
– Michael Green
May 28 at 12:47
@MichaelGreen - is this what you were looking for? dbfiddle.uk/…
– Peter Vandivier
May 28 at 13:44
@PeterVandivier Plagiarism excused :) I was trying to get the recursion working myself so it would handle N levels automatically but couldn't get it quite right
– HandyD
May 28 at 23:52
@PeterVandivier Yes, that's it. I had hoped there was a JSON path "get parent" operator but it seems there is not.
– Michael Green
May 29 at 4:43
add a comment |
This seems to me to be a pretty vanilla recursion query so long as you unwrap the JSON dynamically.
If HandyD will excuse some slight plagiarism...
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH hier ([Level], Parent, Person, staff) AS (
SELECT
1 AS [Level],
convert(nvarchar(255),'') AS Parent,
l1.person,
l1.staff
FROM OPENJSON(@Employees) WITH (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
UNION ALL
select
[Level]+1,
convert(nvarchar(255),h.Person) as Parent,
oj.person,
oj.staff
from hier h
outer apply openjson(h.staff) with (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) oj
where [Level] < 100 -- or relevant maxrecursion level
and oj.Person is not null
)
SELECT
[Level],
Parent,
Person
FROM hier
order by [Level];
Nice. The recursive approach allows for data changes. Can you think of a JSONy way of returning only the single path from Emma to Amy? I know this output forms an adjacency list and I could perform a recursive path walk upwards. I was hoping for something in the JSON itself, if you have a suggestion.
– Michael Green
May 28 at 12:47
@MichaelGreen - is this what you were looking for? dbfiddle.uk/…
– Peter Vandivier
May 28 at 13:44
@PeterVandivier Plagiarism excused :) I was trying to get the recursion working myself so it would handle N levels automatically but couldn't get it quite right
– HandyD
May 28 at 23:52
@PeterVandivier Yes, that's it. I had hoped there was a JSON path "get parent" operator but it seems there is not.
– Michael Green
May 29 at 4:43
add a comment |
This seems to me to be a pretty vanilla recursion query so long as you unwrap the JSON dynamically.
If HandyD will excuse some slight plagiarism...
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH hier ([Level], Parent, Person, staff) AS (
SELECT
1 AS [Level],
convert(nvarchar(255),'') AS Parent,
l1.person,
l1.staff
FROM OPENJSON(@Employees) WITH (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
UNION ALL
select
[Level]+1,
convert(nvarchar(255),h.Person) as Parent,
oj.person,
oj.staff
from hier h
outer apply openjson(h.staff) with (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) oj
where [Level] < 100 -- or relevant maxrecursion level
and oj.Person is not null
)
SELECT
[Level],
Parent,
Person
FROM hier
order by [Level];
This seems to me to be a pretty vanilla recursion query so long as you unwrap the JSON dynamically.
If HandyD will excuse some slight plagiarism...
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH hier ([Level], Parent, Person, staff) AS (
SELECT
1 AS [Level],
convert(nvarchar(255),'') AS Parent,
l1.person,
l1.staff
FROM OPENJSON(@Employees) WITH (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
UNION ALL
select
[Level]+1,
convert(nvarchar(255),h.Person) as Parent,
oj.person,
oj.staff
from hier h
outer apply openjson(h.staff) with (
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) oj
where [Level] < 100 -- or relevant maxrecursion level
and oj.Person is not null
)
SELECT
[Level],
Parent,
Person
FROM hier
order by [Level];
edited May 28 at 12:45
Tom V
14.1k74980
14.1k74980
answered May 28 at 12:19
Peter VandivierPeter Vandivier
1,4851823
1,4851823
Nice. The recursive approach allows for data changes. Can you think of a JSONy way of returning only the single path from Emma to Amy? I know this output forms an adjacency list and I could perform a recursive path walk upwards. I was hoping for something in the JSON itself, if you have a suggestion.
– Michael Green
May 28 at 12:47
@MichaelGreen - is this what you were looking for? dbfiddle.uk/…
– Peter Vandivier
May 28 at 13:44
@PeterVandivier Plagiarism excused :) I was trying to get the recursion working myself so it would handle N levels automatically but couldn't get it quite right
– HandyD
May 28 at 23:52
@PeterVandivier Yes, that's it. I had hoped there was a JSON path "get parent" operator but it seems there is not.
– Michael Green
May 29 at 4:43
add a comment |
Nice. The recursive approach allows for data changes. Can you think of a JSONy way of returning only the single path from Emma to Amy? I know this output forms an adjacency list and I could perform a recursive path walk upwards. I was hoping for something in the JSON itself, if you have a suggestion.
– Michael Green
May 28 at 12:47
@MichaelGreen - is this what you were looking for? dbfiddle.uk/…
– Peter Vandivier
May 28 at 13:44
@PeterVandivier Plagiarism excused :) I was trying to get the recursion working myself so it would handle N levels automatically but couldn't get it quite right
– HandyD
May 28 at 23:52
@PeterVandivier Yes, that's it. I had hoped there was a JSON path "get parent" operator but it seems there is not.
– Michael Green
May 29 at 4:43
Nice. The recursive approach allows for data changes. Can you think of a JSONy way of returning only the single path from Emma to Amy? I know this output forms an adjacency list and I could perform a recursive path walk upwards. I was hoping for something in the JSON itself, if you have a suggestion.
– Michael Green
May 28 at 12:47
Nice. The recursive approach allows for data changes. Can you think of a JSONy way of returning only the single path from Emma to Amy? I know this output forms an adjacency list and I could perform a recursive path walk upwards. I was hoping for something in the JSON itself, if you have a suggestion.
– Michael Green
May 28 at 12:47
@MichaelGreen - is this what you were looking for? dbfiddle.uk/…
– Peter Vandivier
May 28 at 13:44
@MichaelGreen - is this what you were looking for? dbfiddle.uk/…
– Peter Vandivier
May 28 at 13:44
@PeterVandivier Plagiarism excused :) I was trying to get the recursion working myself so it would handle N levels automatically but couldn't get it quite right
– HandyD
May 28 at 23:52
@PeterVandivier Plagiarism excused :) I was trying to get the recursion working myself so it would handle N levels automatically but couldn't get it quite right
– HandyD
May 28 at 23:52
@PeterVandivier Yes, that's it. I had hoped there was a JSON path "get parent" operator but it seems there is not.
– Michael Green
May 29 at 4:43
@PeterVandivier Yes, that's it. I had hoped there was a JSON path "get parent" operator but it seems there is not.
– Michael Green
May 29 at 4:43
add a comment |
You can use OPENJSON and a CTE to extract each person and their associated staff:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH Level1 AS (
SELECT 1 AS Level, NULL AS Parent, l1.person, l1.staff
FROM OPENJSON(@Employees)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
), Level2 AS (
SELECT 2 AS Level, l1.person AS Parent, l2.person, l2.staff
FROM Level1 l1
CROSS APPLY OPENJSON(l1.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l2
), Level3 AS (
SELECT 3 AS Level, l2.person AS Parent, l3.person, l3.staff
FROM Level2 l2
CROSS APPLY OPENJSON(l2.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l3
)
SELECT Level, Parent, Person FROM Level1
UNION
SELECT Level, Parent, Person FROM Level2
UNION
SELECT Level, Parent, Person FROM Level3
ORDER BY Level
Returns:
Level Parent Person
----------------------
1 NULL Amy
2 Amy Bill
2 Amy Chris
3 Chris Emma
3 Chris Dan
Thank you. Two questions 1) how would you return the just the Emma - Chris - Amy path without the other nodes? 2) if we added Frances, reporting to Emma, wouldn't this query have to be extended by another level?
– Michael Green
May 28 at 9:51
add a comment |
You can use OPENJSON and a CTE to extract each person and their associated staff:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH Level1 AS (
SELECT 1 AS Level, NULL AS Parent, l1.person, l1.staff
FROM OPENJSON(@Employees)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
), Level2 AS (
SELECT 2 AS Level, l1.person AS Parent, l2.person, l2.staff
FROM Level1 l1
CROSS APPLY OPENJSON(l1.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l2
), Level3 AS (
SELECT 3 AS Level, l2.person AS Parent, l3.person, l3.staff
FROM Level2 l2
CROSS APPLY OPENJSON(l2.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l3
)
SELECT Level, Parent, Person FROM Level1
UNION
SELECT Level, Parent, Person FROM Level2
UNION
SELECT Level, Parent, Person FROM Level3
ORDER BY Level
Returns:
Level Parent Person
----------------------
1 NULL Amy
2 Amy Bill
2 Amy Chris
3 Chris Emma
3 Chris Dan
Thank you. Two questions 1) how would you return the just the Emma - Chris - Amy path without the other nodes? 2) if we added Frances, reporting to Emma, wouldn't this query have to be extended by another level?
– Michael Green
May 28 at 9:51
add a comment |
You can use OPENJSON and a CTE to extract each person and their associated staff:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH Level1 AS (
SELECT 1 AS Level, NULL AS Parent, l1.person, l1.staff
FROM OPENJSON(@Employees)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
), Level2 AS (
SELECT 2 AS Level, l1.person AS Parent, l2.person, l2.staff
FROM Level1 l1
CROSS APPLY OPENJSON(l1.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l2
), Level3 AS (
SELECT 3 AS Level, l2.person AS Parent, l3.person, l3.staff
FROM Level2 l2
CROSS APPLY OPENJSON(l2.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l3
)
SELECT Level, Parent, Person FROM Level1
UNION
SELECT Level, Parent, Person FROM Level2
UNION
SELECT Level, Parent, Person FROM Level3
ORDER BY Level
Returns:
Level Parent Person
----------------------
1 NULL Amy
2 Amy Bill
2 Amy Chris
3 Chris Emma
3 Chris Dan
You can use OPENJSON and a CTE to extract each person and their associated staff:
declare @Employees nvarchar(max) =
'
"person": "Amy",
"staff": [
"person": "Bill" ,
"person": "Chris",
"staff": [
"person": "Dan" ,
"person": "Emma"
]
]
';
;WITH Level1 AS (
SELECT 1 AS Level, NULL AS Parent, l1.person, l1.staff
FROM OPENJSON(@Employees)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l1
), Level2 AS (
SELECT 2 AS Level, l1.person AS Parent, l2.person, l2.staff
FROM Level1 l1
CROSS APPLY OPENJSON(l1.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l2
), Level3 AS (
SELECT 3 AS Level, l2.person AS Parent, l3.person, l3.staff
FROM Level2 l2
CROSS APPLY OPENJSON(l2.staff)
WITH
(
person NVARCHAR(255),
staff NVARCHAR(MAX) AS JSON
) l3
)
SELECT Level, Parent, Person FROM Level1
UNION
SELECT Level, Parent, Person FROM Level2
UNION
SELECT Level, Parent, Person FROM Level3
ORDER BY Level
Returns:
Level Parent Person
----------------------
1 NULL Amy
2 Amy Bill
2 Amy Chris
3 Chris Emma
3 Chris Dan
answered May 28 at 8:09
HandyDHandyD
2,7921320
2,7921320
Thank you. Two questions 1) how would you return the just the Emma - Chris - Amy path without the other nodes? 2) if we added Frances, reporting to Emma, wouldn't this query have to be extended by another level?
– Michael Green
May 28 at 9:51
add a comment |
Thank you. Two questions 1) how would you return the just the Emma - Chris - Amy path without the other nodes? 2) if we added Frances, reporting to Emma, wouldn't this query have to be extended by another level?
– Michael Green
May 28 at 9:51
Thank you. Two questions 1) how would you return the just the Emma - Chris - Amy path without the other nodes? 2) if we added Frances, reporting to Emma, wouldn't this query have to be extended by another level?
– Michael Green
May 28 at 9:51
Thank you. Two questions 1) how would you return the just the Emma - Chris - Amy path without the other nodes? 2) if we added Frances, reporting to Emma, wouldn't this query have to be extended by another level?
– Michael Green
May 28 at 9:51
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f239180%2ffind-ancestry-from-json%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown