Предполагается, что дети вернутся из базы данных в любом порядке, в котором они решат, намеренно оставив его вне оператора ORDER BY. Вот SQL, который я использовал для создания и заполнения таблицы:
CREATE TABLE Testing
(
ID int,
Title varchar(25),
ParentID int
)
INSERT INTO Testing VALUES (1, 'Parent One', null)
INSERT INTO Testing VALUES (2, 'Parent Two', null)
INSERT INTO TESTING VALUES (3, 'First Child of One', 1)
INSERT INTO TESTING VALUES (4, 'Second Child of One', 1)
INSERT INTO TESTING VALUES (5, 'First Child of Two', 2)
INSERT INTO TESTING VALUES (6, 'Parent Three', null)
Вот код CFM. Я сделал LEFT OUTER JOIN, предполагая, что существуют родители, у которых нет детей. Мне не удалось добавить проверку, чтобы не отображать дочерний «заголовок», если дочерних элементов не существует, но простой CFIF может решить эту проблему для примера. Несмотря на это, я просто пытался показать краткий код, который, я думаю, отвечает на ваш вопрос и направляет вас в правильном направлении:
<cfquery name="myQuery" datasource="Testing">
SELECT C.ParentID, P.TITLE ParentTitle, C.ID ChildID, C.TITLE ChildTitle
FROM Testing P LEFT OUTER JOIN Testing C ON P.ID = C.ParentID
WHERE P.ParentID IS NULL
ORDER BY P.TITLE
</cfquery>
<cfoutput query="myQuery" group="ParentTitle">
Parent = #ParentTitle#<br />
<cfoutput>
Child=#ChildTitle#<br />
</cfoutput>
<hr />
</cfoutput>