This should produce the output you want. Subqueries are definitely the way to go. Trying to use joins just adds complexity that isn't needed.
DECLARE @parents TABLE (ParentID int, [Name] nvarchar(max))
DECLARE @children TABLE (ChildID int, ParentID int, [Name] nvarchar(max), BirthDate datetime)
INSERT @parents (ParentID, [Name]) VALUES (1, 'Bob')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (1,1, 'Billy','4-JUL-2000')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (2,1, 'Joan','19-SEP-2005')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (3,1, 'Sam','20-JAN-2009')
INSERT @parents (ParentID, [Name]) VALUES (2, 'Joe')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (1,2, 'Billy','4-JUL-2000')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (2,2, 'Joan','19-SEP-2005')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (3,2, 'Sam','20-JAN-2009')
INSERT @parents (ParentID, [Name]) VALUES (3, 'Sarah')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (1,3, 'Billy','4-JUL-2000')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (2,3, 'Joan','19-SEP-2005')
INSERT @children (ChildID, ParentID, [Name], BirthDate) VALUES (3,3, 'Sam','20-JAN-2009')
SELECT
A = [Name]
,child =JSON_QUERY((
SELECT [name] = [Name],
[date] = BirthDate
FROM @children c
WHERE c.ParentID = p.ParentID
FOR JSON PATH
))
FROM
@parents p
FOR JSON PATH
I create scalar functions that generate the JSON for the subqueries.
For example (assume that the table variables are actually tables):
CREATE FUNCTION dbo.ChildrenJSON(@ParentID int)
RETURNS nvarchar(max)
BEGIN
RETURN (
SELECT [name] = [Name],
[date] = BirthDate
FROM @children c
WHERE c.ParentID = @ParentID
FOR JSON PATH
)
END
Your query can then look like this:
SELECT
A = [Name]
,child =JSON_QUERY(dbo.ChildrenJSON(ParentID))
FROM
@parents
FOR JSON PATH
It's clean and easy to read.
This is the output:
[
{
"A": "Bob",
"child": [
{
"name": "Billy",
"date": "2000-07-04T00:00:00"
},
{
"name": "Joan",
"date": "2005-09-19T00:00:00"
},
{
"name": "Sam",
"date": "2009-01-20T00:00:00"
}
]
},
{
"A": "Joe",
"child": [
{
"name": "Billy",
"date": "2000-07-04T00:00:00"
},
{
"name": "Joan",
"date": "2005-09-19T00:00:00"
},
{
"name": "Sam",
"date": "2009-01-20T00:00:00"
}
]
},
{
"A": "Sarah",
"child": [
{
"name": "Billy",
"date": "2000-07-04T00:00:00"
},
{
"name": "Joan",
"date": "2005-09-19T00:00:00"
},
{
"name": "Sam",
"date": "2009-01-20T00:00:00"
}
]
}
]