时间限制层次结构的最佳关系数据库表示
题
每个人都认为 SQL 中有时限层次结构的最佳表示是什么?
我的意思是:
- 在任何给定的日期你都有一个正常的树层次结构
- 此层次结构每天都会发生变化
- 每个孩子在任何给定日期仍然只有一位父母
第一天...
Business
|
|-Joe
| |-Happy
| |-Sneezy
| |-Doc(*)
|
|-Moe
|-Bashfull
|-Sleepy
第 2 天...
Business
|
|-Joe
| |-Happy
| |-Sneezy
|
|-Moe
|-Doc(*)
|-Bashfull
|-Sleepy
任何时候,孩子都可以首次加入层次结构,或完全离开层次结构。(例如,新员工和退休员工。)
主要考虑因素:
- 更新层次结构
- 查看某个日期范围内的整个层次结构
- 报告层次结构中的整个子树
- 报告某个日期范围内的整个子树
我现在知道我是如何做到的,但对其其他人如何做到这一点很感兴趣:)
编辑
我天真地假设了一些考虑因素,所以会更明确......
- 每个“团队”或“个人”在其他地方的维度表中都会有一个唯一的 ID
- 其他事实表将使用这些 ID(例如,存储性能指标)
- 该结构需要促进跨日期范围的历史报告
- 使用 ETL 或触发器来维护替代结构是一种选择
通用性是最重要的(仅形成通用关系模式的一部分),并结合驱动报告的易用性(对于任何日期范围内的树的任何部分)以及可靠更新的能力。
解决方案
这里有几本不同的相关书籍 - 一套是关于“时态数据库”的,另一套是关于“RDBMS 中的层次结构”的。
- 斯诺德格拉斯”使用 SQL 开发面向时间的应用程序“(可通过 URL 在线获取 PDF)
- 达特、达尔文和洛伦佐斯”时态数据和关系模型"
- 塞尔科”Joe Celko 为聪明人编写的 SQL 中的树和层次结构"
在我看来,你的问题的棘手部分是:
查看某个日期范围内的整个层次结构
报告某个日期范围内的整个子树
其他项目即使不是直接的,也可以使用书中概述的技术以及其他答案中建议的方式进行管理。部分问题在于理解这两个要点的含义。从某种意义上说,它们是“相同的”;从某种意义上说,它们是“相同的”。“整个层次结构”只是“整个子树”的一个特例。但是,更深层次的问题是“您要如何展示 - 可视化,表示 - 随着时间的流逝,层次结构的变化?”您是否正在寻求在开始和结束时间比较州,还是您也在寻求看到中间变化?您想如何表示层级中个人的举动?
问题多于答案 - 但我希望这些指示能有所帮助。
其他提示
几张平板桌子就可以在这里工作。对于每一行,我们需要列 ID、Name、ParentID 和 InactivatedDatetime(默认为 null)。设置属于 Joe 的旧文档的日期时间,指示该记录不再有效,并将其移至存档表(为了清洁),然后为新文档创建一个新行(原始行的近似副本)以 Moe 的 ID 作为 ParentID。这种方法的缺点是被转移的人必须获得新的身份证,这可能不太方便。
我可以想到一些合理的解决方案,具体取决于您的数据的使用方式及其变化方式。
1)假设今天的等级制度是最重要的。我将在每条记录中使用传统的 ParentId 列存储今天的层次结构。对于以前版本的层次结构,我有一个历史记录表
ItemId, ParentId, ValidFromDate, ValidToDate
每当层次结构发生更改时,您都会向历史表中添加新行。
2)如果任何/所有层次结构都同等重要,我将存储基线层次结构,然后实现层次结构事务表。
TransactionId, ItemId, Action (Move/Delete/Add), DateTime, OldParentId, NewParentId
table item(id, ...)
table item_link(parent_item, child_item, from_date, until_date)
链接将在一定时间内存储树的表示
这种结构代表一个网络而不是一个简单的层次结构,但它支持在层次结构中移动事物,而且还可以回顾过去。应用程序逻辑中需要检查的一些事情是不允许 joe 同时链接到层次结构中的不同位置。
使用 connect by previous Clause(在 Oracle 中),报告相对容易
如果要指定关系上的附加数据,其他详细信息可以与项目甚至项目链接相关。