2010-10-21 87 views
2

使用此示例表:SQL - 订购公用表表达式

drop table Population 
CREATE TABLE [dbo].[Population](
    [PersonId] [int] NOT NULL, 
    [Name] [varchar](50) NOT NULL, 
    [MotherId] [int] NULL, 
    [FatherId] [int] NULL 
) ON [PRIMARY] 
insert Population (PersonId, [Name], MotherId, FatherId) values (1, 'Baby', 2, 3) 
insert Population (PersonId, [Name], MotherId, FatherId) values (2, 'Mother', 4, 5) 
insert Population (PersonId, [Name], MotherId, FatherId) values (3, 'Father', 6, 7) 
insert Population (PersonId, [Name], MotherId, FatherId) values (4, 'Mothers Mother', 8, 9) 
insert Population (PersonId, [Name], MotherId, FatherId) values (5, 'Mothers Father', 99, 99) 
insert Population (PersonId, [Name], MotherId, FatherId) values (6, 'Fathers Mother', 99, 99) 
insert Population (PersonId, [Name], MotherId, FatherId) values (7, 'Father Father', 99, 99) 
insert Population (PersonId, [Name], MotherId, FatherId) values (8, 'Mothers GrandMother', 99, 99) 
insert Population (PersonId, [Name], MotherId, FatherId) values (9, 'Mothers GrandFather', 99, 99) 

我可以用这个SQL返回所有我需要的家谱正确的人

;WITH FamilyTree 
AS 
(
    SELECT *, CAST(NULL AS VARCHAR(50)) AS childName, 0 AS Generation 
    FROM Population 
    WHERE [PersonId] = '1' 

    UNION ALL 

    SELECT Fam.*, FamilyTree.[Name] AS childName, Generation + 1 
    FROM Population AS Fam 
    INNER JOIN FamilyTree 
    ON Fam.[PersonId] = FamilyTree.[motherId] 

    UNION ALL 

    SELECT Fam.*, FamilyTree.[Name] AS childName, Generation + 1 
    FROM Population AS Fam 
    INNER JOIN FamilyTree 
    ON Fam.[PersonId] = FamilyTree.[fatherId] 

) 

SELECT childName, space(generation*2)+name, generation FROM FamilyTree 

它给我:

-baby 
--mother 
--father 
---fathers mother 
---fathers father 
---mothers mother 
---mothers father 

但我怎么能(只是使用sql)把树正确的顺序 - 这样我得到:

-baby 
--mother 
---mothers mother 
---mothers father 
--father 
---fathers mother 
---fathers father 
+0

你可以分享人口和FamilyTree表格的表格设计吗? – InSane 2010-10-21 11:02:12

+0

人口表基本上只是具有personID,名称,motherId,fatherId列的人员列表。 FamilyTree不是物理表,只存在于此查询中。 – simon831 2010-10-21 11:17:34

+0

InSane - 只是给出了示例SQL的问题,以允许您创建表格 – simon831 2010-10-21 13:36:12

回答

3

注意:这个答案在书中的层次章“内部Microsoft SQL Server的T-SQL查询”希望我没有错过任何重要的注意事项非常肤浅的一瞥后,写!

;WITH FamilyTree 
AS 
(
    SELECT *, CAST(NULL AS VARCHAR(50)) AS childName, 0 AS Generation, '.' + CAST([PersonId] AS VARCHAR(max)) + '.' as Path 
    FROM Population 
    WHERE [PersonId] = '1' 

    UNION ALL 

    SELECT Fam.*, FamilyTree.[Name] AS childName, Generation + 1, Path + '0.' + CAST(Fam.[PersonId] AS VARCHAR(max)) + '.' as Path 
    FROM Population AS Fam 
    INNER JOIN FamilyTree 
    ON Fam.[PersonId] = FamilyTree.[MotherId] 

    UNION ALL 

    SELECT Fam.*, FamilyTree.[Name] AS childName, Generation + 1, Path + '1.' + CAST(Fam.[PersonId] AS VARCHAR(max)) + '.' as Path 
    FROM Population AS Fam 
    INNER JOIN FamilyTree 
    ON Fam.[PersonId] = FamilyTree.[FatherId] 

) 

SELECT childName, space(Generation*2)+Name, Generation, Path 
FROM FamilyTree 
ORDER BY Path 
+0

Genius。谢谢。 – simon831 2010-10-21 14:22:06

+0

绝对的辉煌! – Behrens 2013-03-14 12:47:12

0
;WITH FamilyTree 
AS 
(
    SELECT *, CAST(NULL AS VARCHAR(50)) AS childName, 0 AS Generation, CAST(RIGHT('0000000000' + CAST(PersonId as varchar(10)),10) as varchar(max)) as Descendents 
    FROM Population 
    WHERE [PersonId] = '1' 

    UNION ALL 

    SELECT Fam.*, FamilyTree.[Name] AS childName, Generation + 1,FamilyTree.Descendents + '|' + RIGHT('0000000000' + CAST(Fam.PersonId as varchar(10)),10) 
    FROM Population AS Fam 
    INNER JOIN FamilyTree 
    ON Fam.[PersonId] = FamilyTree.[motherId] 

    UNION ALL 

    SELECT Fam.*, FamilyTree.[Name] AS childName, Generation + 1,FamilyTree.Descendents + '|' + RIGHT('0000000000' + CAST(Fam.PersonId as varchar(10)),10) 
    FROM Population AS Fam 
    INNER JOIN FamilyTree 
    ON Fam.[PersonId] = FamilyTree.[fatherId] 

) 

SELECT childName, space(generation*2)+name, generation FROM FamilyTree order by Descendents 

基本上,你要建立一个大的排序关键字,确保所有ID在同一水平在字符串中的相同位置不同。