在族树视图中显示数据的条件

时间:2015-03-28 06:21:12

标签: sql sql-server sql-server-2008

enter image description here

我想在族树中显示数据。我可以很容易地使用下面的查询。我在城市的条件面临问题。如果我搜索city是 paris ,那么它将仅显示属于 paris 的那些数据,但我想显示那些家族头属于 paris <的数据/ em>的。 (如果家庭主人属于 paris 那么显示所有孩子的家长。不需要孩子来自巴黎)。 -1是根级头

; WITH CTE 
AS ( 
    SELECT ROW_NUMBER() OVER (ORDER BY c.ContactId) as MCID , 1 as CID 
    ,c.contactId
    FROM ContactDetail c where c.FamilyHeadId = -1
    UNION ALL
    SELECT cte.MCID as MCID ,
    CONVERT(INT,(
                    CONVERT(VARCHAR(10),CTE.CID) + 
                    CONVERT(VARCHAR(10),ROW_NUMBER() OVER (ORDER BY p.ContactId))
                )
            ) AS CID

    ,p.contactId
    FROM ContactDetail p INNER JOIN cte ON p.FamilyHeadId = CTE.ContactId

)

select * from CTE 
inner join ContactDetail b on cte.contactid = b.contactid 
order by mcid,CID 

3 个答案:

答案 0 :(得分:2)

您可以移动过滤器&#34; Paris&#34;进入CTE的初始锚定查询(即家庭负责人的搜索也将受到城市的限制)。但是,在CTE中UNION之后的递归查询中不得重复此谓词(因为不需要约束子项)。我在CityName上假设了一列ContactDetail,但可能您的实际模型与City表格之间存在规范化关系:

; WITH CTE 
 AS ( 
    SELECT ROW_NUMBER() OVER (ORDER BY c.ContactId) as MCID, 1 as CID, c.contactId
    FROM ContactDetail c 
    WHERE c.FamilyHeadId = -1 AND c.City = 'Paris'

    UNION ALL

    SELECT cte.MCID as MCID,
        CONVERT(INT, (CONVERT(VARCHAR(10),CTE.CID) + 
            CONVERT(VARCHAR(10),ROW_NUMBER() OVER (ORDER BY p.ContactId)))) AS CID
        ,p.contactId
    FROM ContactDetail p 
        INNER JOIN cte ON p.FamilyHeadId = CTE.ContactId

)
SELECT * FROM CTE 
INNER JOIN ContactDetail b on cte.contactid = b.contactid 
order by mcid, CID;

SqlFiddle here

请注意,您还可以通过根据updated SqlFiddle

从2个CTE查询中发出所有必填字段,避免外部查询中的最终连接返回到同一个表。

答案 1 :(得分:0)

实际上变量表可能比光标更好,所以我利用plz检查这个查询它应该帮助你。

declare  @allheadCount int, @allheadCounttree int , @contactId int 
declare  @city varchar(50), @name varchar(50)

set @allheadCounttree =0

DECLARE @familyTree TABLE
(
familyId int IDENTITY(1,1),
contactId int ,
familyHeadId int,
Name varchar(50) NOT NULL,
city varchar(50) NOT NULL,
headcity varchar(50) NOT NULL
)

select @allheadCount = count(contactid) from contactdetail where familyheadid = -1

WHILE @allheadCount <> @allheadCounttree 
BEGIN

    select top 1 @contactid = contactId, @name=name, @city=city from contactdetail where familyheadid = -1 and contactid not in (select distinct contactid from @familytree )

    insert into @familyTree (contactid,familyheadid,name,city,headcity) Values (@contactId,-1,@name,@city,@city) 

    insert into @familyTree (contactid,familyheadid,name,city,headcity) 
    select contactid,@contactId,name,city,@city from contactdetail where familyheadid = @contactid

    select @allheadCounttree  = count(contactid) from @familyTree where familyheadid = -1

END

select  * from @familyTree where city = lower('Paris') or headcity = lower('paris') order by familyid

答案 2 :(得分:-1)

    select * from contactdetail where city = lower('paris')
    union
    select contactId, FamilyHeadId, Name, City from contactdetail cross apply (
        select contactid as pcontactid, city as pcity from contactdetail where familyheadid = -1 
    ) parentdata
        where pcity =  lower('paris') and pcontactid = familyheadid