You can build almost any XML using FOR XML PATH.
In this case, if you need 2 levels:
select [Key] as "@key", '' as "@parentkey", (select [Key] as "@key", [ParentKey] as "@parentkey" from KEY_TABLE t1 where [ParentKey] = t.[Key] for xml path('record'), type) from KEY_TABLE t where [ParentKey] is null for xml path ('record')
for 3 levels, you need to write another subquery, for example:
select [Key] as "@key", '' as "@parentkey", (select [Key] as "@key", [ParentKey] as "@parentkey", (select [Key] as "@key", [ParentKey] as "@parentkey" from KEY_TABLE t2 where [ParentKey] = t1.[Key] for xml path('record'), type) from KEY_TABLE t1 where [ParentKey] = t.[Key] for xml path('record'), type) from KEY_TABLE t where [ParentKey] is null for xml path ('record')
must do it.
A subquery can be easily reorganized into a recursive function like:
create function SelectChild(@key as int) returns xml begin return ( select [Key] as "@key", [ParentKey] as "@parentkey", dbo.SelectChild([Key]) from KEY_TABLE where [ParentKey] = @key for xml path('record'), type ) end
Then you can get what you need,
select [Key] as "@key", '' as "@parentkey", dbo.SelectChild([Key]) from KEY_TABLE where [ParentKey] is null for xml path ('record')
Recep
source share