【问题标题】:Split data by levels in hierarchy在层次结构中按级别拆分数据
【发布时间】:2018-10-11 09:37:24
【问题描述】:

初始数据示例:

| ID   |  ParentID  |
|------|------------|
|  1   |    NULL    |
|  2   |     1      |
|  3   |     1      |
|  4   |     2      |
|  5   |    NULL    |
|  6   |     2      |
|  7   |     3      |

在我的初始数据中,我有元素的 ID 和他的父 ID。 有些元素有父元素,有些没有,有些元素有父元素,而他的父元素也有父元素。

此层次结构中的最大级别数为 3。

我需要逐级获取此层次结构。

Lvl 1 - 没有父元素的元素 Lvl 2 - 有父元素但没有父元素的元素 Lvl 3 - 有父元素的元素也有父元素。

预期结果如下:

| Lvl1  |   Lvl2   |   Lvl3   |
|-------|----------|----------|
|  1    |   NULL   |   NULL   |
|  1    |    2     |   NULL   |
|  1    |    3     |   NULL   |
|  1    |    2     |    4     |
|  5    |   NULL   |   NULL   |
|  1    |    2     |    6     |
|  1    |    3     |    7     |

我该怎么做?

【问题讨论】:

  • 知道确定你需要达到最大深度吗lvl3,这个不会改变?如果它是灵活/动态/可变的,那么这通常不是一个好主意,问题就变成了;你为什么要这样做,你会用它做什么?可能有更好的选择,SQL 喜欢你开始的规范化结构。
  • @MatBailie 我只需要这个视图来报告,是的,最大深度不会改变,它总是 3。
  • 即使是报告,这也往往是错误的方向。询问有关如何编写示例报告的问题可能会更好地为您服务。向我们展示您将开始使用的数据,向我们展示您想要的最终报告,告诉我们您将使用哪种报告应用程序,然后我们可以帮助您找到合适的模式,而不是“仅仅”向您展示如何实施通常是一种反模式。

标签: sql sql-server sql-server-2017


【解决方案1】:

对于固定的三个部门,您可以使用CROSS APPLY

它可以像JOIN 一样使用,但也可以返回额外的记录给你NULLs。

SELECT
  Lvl1.ID   AS lvl1,
  Lvl2.ID   AS lvl2,
  Lvl3.ID   AS lvl3
FROM
  initial_data   AS Lvl1
CROSS APPLY
(
   SELECT ID FROM initial_data WHERE ParentID = Lvl1.ID
   UNION ALL
   SELECT NULL AS ID
)
  AS Lvl2
CROSS APPLY
(
   SELECT ID FROM initial_data WHERE ParentID = Lvl2.ID
   UNION ALL
   SELECT NULL AS ID
)
  AS Lvl3
WHERE
  Lvl1.ParentID IS NULL
ORDER BY
  Lvl1.ID,
  Lvl2.ID,
  Lvl3.ID

但是,根据我的评论,这通常表明您正在走非 sql 路线。开始时可能会感觉更容易,但后来它会转而咬你,因为 SQL 极大地受益于标准化结构(你的起始数据)。

【讨论】:

  • 谢谢,它有效,但也非常感谢您详细解释此决定的不良做法。
猜你喜欢
  • 2015-06-25
  • 1970-01-01
  • 2013-07-04
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-17
  • 1970-01-01
相关资源
最近更新 更多