将多列的值组合到一列中

时间:2013-06-07 17:57:13

标签: sql sql-server

我有一个由A,B,C,D组成的层次结构。每个实体与其子女具有一对多的关系(A - > 1:N - > B - > 1:N - > C - > 1:N - > D)。
我有另一个实体,我们称之为X,可以使用LevelIDLevelTypeID字段链接到其中一个层次结构实体(LevelID是A,B,C的外键或D和LevelTypeID是查找表的外键,其中包含A,B,C和D的名称。

基于提供的LevelIDLevelTypeID,我需要一个查询,它可以为我提供当前的层次结构实体和任何更高级的父级实体。

以下是4个表格中的一些示例数据

   A
         ID       
         --
         1       
   B
         ID       A_ID
         ----     -----     
         10       1
   C
         ID       B_ID
         ----     -----
         100      10
   D
         ID       C_ID
         -----    -----
         1000     100
         1001     100

使用 LevelId = 100,LevelTypeId = 3 (C),查询应返回:

   LevelTypeId    LevelId
   -----------    -------
   3               100
   2               10
   1               1

使用 LevelId = 1000,LevelTypeId = 4 (D),查询应返回:

   LevelTypeId    LevelId
   -----------    -------
   4               1000
   3               100
   2               10
   1               1

我正在使用下面的查询,但我没有得到正确的结果,特别是当我过滤 LevelId = 100,LevelTypeId = 3

select LevelTypeId, LevelId
from
   (    select  
            a.ID as [1], 
            b.ID as [2],
            c.ID as [3], 
            d.ID as [4]
        from A a
        left join B b on a.ID = b.A_ID
        left join C c on b.ID = c.B_ID
        left join D d on c.ID = d.C_ID
        where 
            (@levelTypeId = 4 and D.ID = @levelId)
            or
            (@levelTypeId = 3 and C.ID = @levelId)
            or
            (@levelTypeId = 2 and B.ID = @levelId)
            or
            (@levelTypeId = 1 and A.ID = @levelId)

   ) p   
unpivot
   (LevelId FOR LevelTypeId IN ([1], [2], [3], [4])) AS unpvt

有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

现有查询返回联接中的所有级别,因为where子句中只有级别选择 - 如果任何级别符合条件,则 all < / em>级别被选中。相反,尝试:

select LevelTypeId, LevelId
from
   (    select  
            a.ID as [1], 
            b.ID as [2],
            c.ID as [3], 
            d.ID as [4]
        from A a
        left join B b on a.ID = b.A_ID and @levelTypeId >= 2
        left join C c on b.ID = c.B_ID and @levelTypeId >= 3
        left join D d on c.ID = d.C_ID and @levelTypeId >= 4
        where 
            (@levelTypeId = 4 and D.ID = @levelId)
            or
            (@levelTypeId = 3 and C.ID = @levelId)
            or
            (@levelTypeId = 2 and B.ID = @levelId)
            or
            (@levelTypeId = 1 and A.ID = @levelId)

   ) p   
unpivot
   (LevelId FOR LevelTypeId IN ([1], [2], [3], [4])) AS unpvt

SQLFiddle here