You are using the Adjacency List model, where it is difficult to enforce such a constraint.
You can examine the Nested Set model, where only true hierarchies can be represented (no circular paths). This has other drawbacks though, like slow Inserts/Updates.
I found the answer - I needed to create a CTE
that uses a union of all my child and parent records and creates a ROW_NUMBER()
, then JOIN
to that CTE
to get the ROW_NUMBER()
value which will be unique across all records.
Solution fiddle here.
Full solution to paste into SSMS:
BEGIN TRY
DROP TABLE #Child
DROP TABLE #Parent
END TRY
BEGIN CATCH
END CATCH
CREATE TABLE #Parent
(RecId int PRIMARY KEY NOT NULL,
PersonName varchar(100), Age int)
CREATE TABLE #Child
(ChildID int identity PRIMARY KEY NOT NULL,
ParentRecId int FOREIGN KEY REFERENCES #Parent(RecId),
SalesAmt money)
INSERT INTO #Parent
(RecID, PersonName, Age)
VALUES
(1, 'Aaron Bertrand', 99),
(2, 'Paul White', 20),
(3, 'JNK', 33)
INSERT INTO #Child
(ParentRecID, SalesAmt)
VALUES
(1, 10.00),
(1, 20.00),
(2, 15.15),
(2, 100.00),
(3, 0.00)
;WITH IDs AS
(
SELECT
RN = (ROW_NUMBER() OVER (ORDER BY RecId,CASE WHEN ChildId IS NULL THEN 0 ELSE 1 END) -1),
RecId,
ChildId
FROM
(
SELECT
RecId, ChildId = NULL
FROM
#Parent
UNION ALL
SELECT
RecId, ChildId
FROM
#Parent P
INNER JOIN
#Child C
ON C.ParentRecId = P.RecId) x
)
SELECT
P.RecId as 'RID',
P.PersonName as 'PNAM',
P.Age,
I.RN as 'Index',
(
SELECT
C.SalesAmt as 'SAMT',
I.RN as 'Index'
FROM
#Child C
INNER JOIN
IDs I
ON I.ChildId = C.ChildID
WHERE
C.ParentRecId = P.RecId
FOR XML PATH ('ChildRec'), ROOT ('ChildRecs'), TYPE
)
FROM
#Parent P
INNER JOIN
IDs I
ON I.RecId = P.RecId
AND I.ChildId IS NULL
FOR XML PATH ('Parent'), ROOT ('Parents'), TYPE
Best Answer
Looks like a
GROUP_CONCAT
to me, unless I'm missing something, egMy results: