SELECT наследует значения от родителя в иерархии - PullRequest
2 голосов
/ 03 февраля 2012

Я пытаюсь получить через 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 ]

3 голосов
/ 03 февраля 2012

Использование:

;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
0 голосов
/ 03 февраля 2012

Может быть, что-то вроде этого:

;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
0 голосов
/ 03 февраля 2012

Один из способов сделать это:

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
...