【问题标题】:Create column that stores hierarchy as comma separated values创建将层次结构存储为逗号分隔值的列
【发布时间】:2016-01-24 19:33:14
【问题描述】:

我有一个表,它有两列 UNITM_UNIT,如下所示:

+--------+--------+ |单位 | M_UNIT | +--------+--------+ | 10 | 12 | | 15 | 19 | | 12 | 16 | | 13 | 15 | | 19 | 14 | | 14 | 11 | +--------+--------+

我想创建一个列 H_TREE,在递归搜索 UNIT 和 M_UNIT 后将层次结构存储为逗号分隔值,这样 H_TREE 以 UNIT 开头并以最后一个可能的 M_UNIT 结尾,如下所示:

+--------+--------+----------------+ |单位 | M_UNIT | H_TREE | +--------+--------+----------------+ | 10 | 12 | 10,12,16 | | 15 | 19 | 15,19,14,11 | | 12 | 16 | 12,16 | | 13 | 15 | 13,15,19,14,11 | | 19 | 14 | 19,14,11 | | 14 | 11 | 14,11 | +--------+--------+----------------+

如果我不够清楚,请道歉,如果有什么令人困惑的地方,请告诉我。谢谢。

【问题讨论】:

  • 我删除了无关的数据库选项卡。请为您正在使用的数据库添加适当的标签。

标签: sql hierarchy hierarchical-data


【解决方案1】:

这应该会产生你想要的:

WITH data (unit, m_unit) AS (
    SELECT 10, 12 FROM dual UNION ALL
    SELECT 15, 19 FROM dual UNION ALL
    SELECT 12, 16 FROM dual UNION ALL
    SELECT 13, 15 FROM dual UNION ALL
    SELECT 19, 14 FROM dual UNION ALL
    SELECT 14, 11 FROM dual)
SELECT
    unit,
    m_unit,
    unit || ',' || listagg(root_unit, ',') WITHIN GROUP (ORDER BY depth) h_tree
FROM (
    SELECT
        id, unit, m_unit,
        LEVEL depth, CONNECT_BY_ROOT m_unit root_unit
    FROM
        (SELECT ROWNUM id, unit, m_unit FROM data) data
    CONNECT BY
        PRIOR unit = m_unit)
GROUP BY
    id,
    unit,
    m_unit

如果表中的行不同,则不需要 id 列。

【讨论】:

  • 感谢您的回复 Husqvik,您有一个很好的解决方案。正如你所说,我已经编辑了 H_TREE 的第一行。
【解决方案2】:

你不应该这样做。您应该有一个名为 ParentID 或其他内容的列。然后在需要时构建树。

这是一个将所有内容连接在一起的示例(SQL Server):

USE AdventureWorks2008R2;
GO
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
-- Anchor member definition
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID, 
        0 AS Level
    FROM dbo.MyEmployees AS e
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
        ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
    WHERE ManagerID IS NULL
    UNION ALL
-- Recursive member definition
    SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
        Level + 1
    FROM dbo.MyEmployees AS e
    INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
        ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
    INNER JOIN DirectReports AS d
        ON e.ManagerID = d.EmployeeID
)
-- Statement that executes the CTE
SELECT ManagerID, EmployeeID, Title, DeptID, Level
FROM DirectReports
INNER JOIN HumanResources.Department AS dp
    ON DirectReports.DeptID = dp.DepartmentID
WHERE dp.GroupName = N'Sales and Marketing' OR Level = 0;
GO

【讨论】:

    【解决方案3】:
    WITH data (unit, m_unit) AS (
        SELECT unit, m_unit from TABLE)
    SELECT
        unit,
        m_unit,
        unit || ',' || listagg(root_unit, ',') WITHIN GROUP (ORDER BY depth)   h_tree
    FROM (
    SELECT
        id, unit, m_unit,
        LEVEL depth, CONNECT_BY_ROOT m_unit root_unit
    FROM
        (SELECT ROWNUM id, unit, m_unit FROM data) data
    CONNECT BY
        PRIOR unit = m_unit)
    GROUP BY
        id,
        unit,
        m_unit
    

    我选择了 Husqvik 的答案,并使用了一个有 500 行的表格,它运行良好。感谢大家的回复。

    【讨论】:

      猜你喜欢
      • 2016-05-03
      • 2020-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      相关资源
      最近更新 更多