SELECT从层次结构中的父级继承值

时间:2012-02-03 13:56:10

标签: sql sql-server tsql common-table-expression

我试图通过T-SQL(在存储过程中)实现在检索行时将值从父级复制到子级中的方法。以下是一些示例数据:

DROP TABLE TEST_LEVELS
CREATE TABLE TEST_LEVELS(
     ID INT NOT NULL
    ,VALUE INT NULL
    ,PARENT_ID INT NULL
    ,LEVEL_NO INT NOT NULL
)

INSERT INTO TEST_LEVELS (ID, VALUE, PARENT_ID, LEVEL_NO) VALUES (1, 10000, NULL, 1)
INSERT INTO TEST_LEVELS (ID, VALUE, PARENT_ID, LEVEL_NO) VALUES (2, NULL, 1, 2)
INSERT INTO TEST_LEVELS (ID, VALUE, PARENT_ID, LEVEL_NO) VALUES (3, NULL, 2, 3)
INSERT INTO TEST_LEVELS (ID, VALUE, PARENT_ID, LEVEL_NO) VALUES (4, 20000, NULL, 1)
INSERT INTO TEST_LEVELS (ID, VALUE, PARENT_ID, LEVEL_NO) VALUES (5, NULL, 4, 2)
INSERT INTO TEST_LEVELS (ID, VALUE, PARENT_ID, LEVEL_NO) VALUES (6, 25000, 5, 3)
INSERT INTO TEST_LEVELS (ID, VALUE, PARENT_ID, LEVEL_NO) VALUES (7, NULL, 6, 4)

按如下方式选择数据:

SELECT ID, VALUE, LEVEL_NO
FROM TEST_LEVELS

结果:

+----+-------+----------+
| ID | VALUE | LEVEL_NO |
+----+-------+----------+
|  1 | 10000 |        1 |
|  2 | NULL  |        2 |
|  3 | NULL  |        3 |
|  4 | 20000 |        1 |
|  5 | NULL  |        2 |
|  6 | 25000 |        3 |
|  7 | NULL  |        4 |
+----+-------+----------+

但我需要这样的东西(值由父母继承):

+----+-------+----------+
| ID | VALUE | LEVEL_NO |
+----+-------+----------+
|  1 | 10000 |        1 |
|  2 | 10000 |        2 |
|  3 | 10000 |        3 |
|  4 | 20000 |        1 |
|  5 | 20000 |        2 |
|  6 | 25000 |        3 |
|  7 | 25000 |        4 |
+----+-------+----------+

这可以在不使用游标的情况下实现(它还必须在SQL Server 2005上运行)吗?

3 个答案:

答案 0 :(得分:3)

使用:

;with cte
as
(
    select t.ID, t.VALUE, t.PARENT_ID, t.LEVEL_NO
    from @t t
    where t.Value is not null

    union all 

    select t.ID, c.Value, t.PARENT_ID, t.LEVEL_NO
    from cte c
    join @t t on t.PARENT_ID = c.ID
    where t.Value is null
)

select c.ID, c.Value, c.LEVEL_NO
from cte c
order by c.ID

输出:

ID          Value       LEVEL_NO
----------- ----------- -----------
1           10000       1
2           10000       2
3           10000       3
4           20000       1
5           20000       2
6           25000       3
7           25000       4

答案 1 :(得分:0)

也许是这样的:

;WITH cte_name(ID,VALUE,PARENT_ID,LEVEL_NO)
AS
(
    SELECT
        tbl.ID,
        tbl.VALUE,
        tbl.PARENT_ID,
        tbl.LEVEL_NO
    FROM
        TEST_LEVELS AS tbl
    WHERE 
        tbl.PARENT_ID IS NULL
    UNION ALL
    SELECT
        tbl.ID,
        ISNULL(tbl.VALUE,cte_name.VALUE),
        tbl.PARENT_ID,
        tbl.LEVEL_NO
    FROM
        cte_name
        JOIN TEST_LEVELS AS tbl
            ON cte_name.ID=tbl.PARENT_ID

)
SELECT
    *
FROM 
    cte_name
ORDER BY 
    ID

答案 2 :(得分:-1)

一种方法:

SELECT T.ID,
    case when T.VALUE IS NULL
    THEN (SELECT A.VALUE FROM TEST_LEVELS A WHERE A.ID = T.PARENT_ID)
    ELSE T.VALUE
    END,
    T.LEVEL_NO
FROM TEST_LEVELS T