如何为此平面数据结构创建父/父id列?

时间:2013-07-13 08:12:07

标签: sql-server

我有一张像这样的桌子

ID  L1          L2              L3                  OBId                    OBDesc      ParentId
1   3501-072                                        3501-072-0102           building1   ?
2   3501-072    3501-072-0102                       3501-072-0102-0001      room2       ?
3   3501-072    3501-072-0102   3501-072-0102-0001  3501-072-0102-0001-0001 table1      ?
4   3501-072    3501-072-0102   3501-072-0102-0001  3501-072-0102-0001-0002 chair1      ?
5   3501-072    3501-072-0102                       3501-072-0102-0003      room3       ?
6   3501-072    3501-072-0102   3501-072-0102-0003  3501-072-0102-0003-0001 Table2      ?
7   3501-072    3501-072-0102   3501-072-0102-0003  3501-072-0102-0003-0002 chair3      ?

结构基本上是,table1属于bulding1中的room2。

列L1,L2,L3等是表示此的层次结构级别。

OBId是层次结构中每个节点的唯一编号

我需要一个查询,可以将ParentId与下一个节点中的ID进行对比。

欢迎任何想法......

我有一张像这样的桌子

ID  L1          L2              L3                  OBId                    OBDesc      ParentId
1   3501-072                                        3501-072-0102           building1   ?
2   3501-072    3501-072-0102                       3501-072-0102-0001      room2       ?
3   3501-072    3501-072-0102   3501-072-0102-0001  3501-072-0102-0001-0001 table1      ?
4   3501-072    3501-072-0102   3501-072-0102-0001  3501-072-0102-0001-0002 chair1      ?
5   3501-072    3501-072-0102                       3501-072-0102-0003      room3       ?
6   3501-072    3501-072-0102   3501-072-0102-0003  3501-072-0102-0003-0001 Table2      ?
7   3501-072    3501-072-0102   3501-072-0102-0003  3501-072-0102-0003-0002 chair3      ?

结构基本上是,table1属于bulding1中的room2。

列L1,L2,L3等是表示此的层次结构级别。

OBId是层次结构中每个节点的唯一编号

我需要一个查询,可以使用下一个节点的ID来填充ParentId。

欢迎任何想法......

- - - - - - - - UPDATE

为了简化这个例子,我没有提到总共有10个潜在的水平

2 个答案:

答案 0 :(得分:2)

如果L2和L3中有空值而不是空字符串,则可以使用COALESCE

SELECT COALESCE(L3,L2,L1) as Parent FROM tablename

否则你可以使用案例陈述

SELECT CASE WHEN isnull(L2,'') = '' then L1
            WHEN isnull(L3,'') = '' then L2
            ELSE L3
       END as Parent 
FROM tablename

修改 更新看起来像:

update tablename 
SET parent = CASE WHEN isnull(L2,'') = '' then L1
                WHEN isnull(L3,'') = '' then L2
                ELSE L3
             END

答案 1 :(得分:1)

假设L1,L2,L3结构是固定的(意味着层次结构的深度不超过3级),我将使用以下方法:只需编写一个查询来更新层次结构的每个级别的值。如果层次结构达到4或5级,因为查询开始变得难以处理,这种方法会中断,但它应该可以正常工作3个级别。如果我不得不支持更多级别的层次结构(或变量级别),我可能会提出一个更通用的解决方案(可能会使用CURSOR)。

我整理了以下示例,该示例可以为您提供所需的结果。此示例假定L2和L3为空('')而不是NULL。我把它放在一起时注意到的一件事是你提供的样本数据似乎没有效果(记录2和5的L1和L2是相同的,这意味着子记录可能有2个父记录),所以我在写作中纠正了它。

DECLARE @myTable AS TABLE
(
    ID INT,
    L1 VARCHAR(50),
    L2 VARCHAR(50),
    L3 VARCHAR(50),
    OBId VARCHAR(50),
    OBDesc VARCHAR(50),
    ParentID INT NULL
)
INSERT INTO @myTable VALUES(1, '3501-072', '', '', '3501-072-0102', 'building1', NULL)
INSERT INTO @myTable VALUES(2, '3501-072', '3501-072-0102', '', '3501-072-0102-0001', 'room2', NULL)
INSERT INTO @myTable VALUES(3, '3501-072', '3501-072-0102', '3501-072-0102-0001', '3501-072-0102-0001-0001', 'table1', NULL)
INSERT INTO @myTable VALUES(4, '3501-072', '3501-072-0102', '3501-072-0102-0001', '3501-072-0102-0001-0002', 'chair1', NULL)
INSERT INTO @myTable VALUES(5, '3501-072', '3501-072-0103', '', '3501-072-0103-0003', 'room3', NULL)
INSERT INTO @myTable VALUES(6, '3501-072', '3501-072-0103', '3501-072-0103-0003', '3501-072-0102-0003-0001', 'Table2', NULL)
INSERT INTO @myTable VALUES(7, '3501-072', '3501-072-0103', '3501-072-0103-0003', '3501-072-0102-0003-0002', 'chair3', NULL)

--Update records with no parent ID
UPDATE @myTable SET ParentID = NULL WHERE L2 = '' AND L3 = ''

--Update first level
UPDATE @myTable 
SET ParentID = (
    SELECT ID 
    FROM @myTable T2 
    WHERE 
        T2.L1 = T1.L1 
        AND T2.L2 = '' 
        AND T2.L3 = ''
) 
FROM @myTable T1
WHERE T1.L2 <> '' AND T1.L3 = ''

--Update second level
UPDATE @myTable 
SET ParentID = (
    SELECT ID FROM @myTable T2 
    WHERE 
        T2.L1 = T1.L1 
        AND T2.L2 = T1.L2 
        AND T2.L3 = ''
        AND T1.L2 <> ''
) 
FROM @myTable T1
WHERE T1.L2 <> '' AND T1.L3 <> ''

--Select results
SELECT ID, L1, L2, L3, ParentID FROM @myTable

希望有所帮助。