通过自联接从任何更高级别获取树中的最低级别

时间:2014-09-10 14:45:48

标签: sql sql-server

使用sql server 2012,我有一个看起来像这样的表:

Type | Code  | Parent_Type | Parent_Code
  4  | 123   |     2       |     1
  4  | 234   |     2       |     1
  6  | 1234  |     4       |     123 
  6  | 2345  |     4       |     234
  7  | 12345 |     6       |     1234
  7  | 23456 |     6       |     1234
  7  | 34567 |     6       |     2345

它将父类型/代码组合映射到子类型/代码组合。它将类型2映射到类型4,将4映射到类型6,将6映射到类型7.如果我查找Parent_Type 2Parent_Code 1的所有记录}:

select * from mytable where parent_type = 2 and parent_code = 1

它将返回:

Type | Code  | Parent_Type | Parent_Code
  4  | 123   |     2       |     1
  4  | 234   |     2       |     1

我想要做的是找出最终的方法来获得所有类型7代码,这些代码都存在于最终的父类型1代码中。另外,我需要这个适用于任何类型级别。所以我希望能够在类型4代码下获得类型7代码,或者甚至使用类型7代码(只返回单个匹配行)。

所以我在搜索parent_type = 2 and parent_code = 1时希望看到的是:

Type | Code  | Parent_Type | Parent_Code
  7  | 12345 |     6       |     1234
  7  | 23456 |     6       |     1234
  7  | 34567 |     6       |     2345

但如果我是从parent_type = 4 and parent_code = 123

开始的话
Type | Code  | Parent_Type | Parent_Code
  7  | 12345 |     6       |     1234
  7  | 23456 |     6       |     1234

我最初尝试过这个:

select grandchild.type
       grandchild.code
       parent.parent_type
       parent.parent_code
from mytable as parent
join mytable as child on parent.code = child.parent_code
join mytable as grandchild on child.code = grandchild.parent_code
where parent.parent.code = 1

如果你从类型2代码开始,但在任何其他级别失败(不返回任何结果),那么它的效果很好。

所以我搜索了一下,然后回答了这个问题并回答:https://stackoverflow.com/a/1757302/1250301

尝试了这个:

with q as
(
    select * 
    from mytable
    where parent_type = 2
    union all
    select m.*
    from mytable m
    join q
    on m.parent_code = q.code
)
Select *
from q where parent_code = 1

但仍然只能在一个级别上返回与我的初始select查询相同的结果。

如何从高级代码开始选择所有7级代码?

注意,我的最终目标是将此结果与另一个类型/代码组合表(具有可能的混合类型)结合,将其转换为所有7级代码的列表(然后将其与另一个包含数据的表连接我需要,但只在7级代码级别。)

1 个答案:

答案 0 :(得分:2)

这有效:

DECLARE @parent_type INT, @parent_code INT
SET @parent_type = 2
SET @parent_code = 1;

WITH CTE AS
(
    SELECT *
    FROM YourTable
    WHERE (parent_type = @parent_type AND parent_code = @parent_code) OR (type = @parent_type AND code = @parent_code)
    UNION ALL
    SELECT B.*
    FROM CTE A
    INNER JOIN YourTable B
        ON A.Code = B.Parent_Code
)
SELECT *
FROM CTE
WHERE Type = 7;

Here is a sqlfiddle及其演示。

parent_type = 2parent_code = 1的结果是:

╔══════╦═══════╦═════════════╦═════════════╗
║ Type ║ Code  ║ Parent_Type ║ Parent_Code ║
╠══════╬═══════╬═════════════╬═════════════╣
║    7 ║ 34567 ║           6 ║        2345 ║
║    7 ║ 12345 ║           6 ║        1234 ║
║    7 ║ 23456 ║           6 ║        1234 ║
╚══════╩═══════╩═════════════╩═════════════╝

parent_type = 4parent_code = 123

╔══════╦═══════╦═════════════╦═════════════╗
║ Type ║ Code  ║ Parent_Type ║ Parent_Code ║
╠══════╬═══════╬═════════════╬═════════════╣
║    7 ║ 12345 ║           6 ║        1234 ║
║    7 ║ 23456 ║           6 ║        1234 ║
╚══════╩═══════╩═════════════╩═════════════╝