【发布时间】:2011-06-17 13:04:09
【问题描述】:
我的直觉告诉我,开始时间和结束时间通常比开始时间和持续时间要好,但我想知道不同方法是否有一些具体的优点或缺点。
我看到的 strttime 和 endtime 的优势是,如果您想在某个时间段内调用所有活动,则不必查看该时间段之外的内容。
(这是针对在初始输入后不太可能发生太大变化并且与特定时间相关联的事件,如果有影响的话)
【问题讨论】:
标签: sql events database-design duration
我的直觉告诉我,开始时间和结束时间通常比开始时间和持续时间要好,但我想知道不同方法是否有一些具体的优点或缺点。
我看到的 strttime 和 endtime 的优势是,如果您想在某个时间段内调用所有活动,则不必查看该时间段之外的内容。
(这是针对在初始输入后不太可能发生太大变化并且与特定时间相关联的事件,如果有影响的话)
【问题讨论】:
标签: sql events database-design duration
我不认为这是一种偏好或个人选择。计算机科学是一门科学,我们是编程机器,而不是敏感的孩子。
重新发明轮子
业界巨头已就关系数据库中的时间数据这一主题撰写了整本书。 Codd 已去世,但他的同事和合著者 C J Date 以及最近的 H Darwen 在第三宣言中继续推进和完善关系模型的工作。关于该主题的开创性著作是 C J Date、Hugh Darwen 和 Nikos 所著的Temporal Data & the Relational Model 一个洛伦佐斯。
有很多人发表关于 CS 科目的意见和个人选择,就好像他们在选择冰淇淋一样。这是由于没有接受过任何正式培训,因此将他们的 CS 任务视为地球上唯一遇到该问题并找到解决方案的人。基本上,他们从头开始重新发明轮子,就好像不存在其他轮子一样。阅读技术资料(不包括 Wikipedia 和 MS 出版物)可以节省大量时间和精力。
购买现代车轮
时态数据一直是数以千计遵循 RM 并试图实施良好解决方案的数据建模者处理的问题。其中一些是好的,而另一些则不是。但现在我们有巨头的工作,经过认真研究,并提供了解决方案和规定的治疗方法。和以前一样,这些最终将在 SQL 标准中实现。 PostgreSQL 已经有几个必需的函数(作者是 TTM 的一部分)。
因此,我们可以采用那些 (a) 经得起未来考验且 (b) 可靠(与目前存在的数千个不太好的时间数据库不同)的解决方案和处方,而不是依赖任何个人意见,或某些网站上的热门投票。不用说,代码也会简单得多。
购买前检查
如果您进行一些谷歌搜索,请注意也有非常糟糕的“书籍”可用。这些是在 MS 和 Oracle 的旗帜下由在冰淇淋店度过一生的博士出版的。因为他们没有阅读和理解教科书,他们对问题的理解很肤浅,并且发明了相当不正确的“解决方案”。然后他们继续提供大量解决方案,不是针对时间数据,而是针对其“解决方案”中固有的大量问题。您将被锁定在已识别且唯一的问题中;并实现触发器和各种不必要的代码。任何免费提供的东西都物有所值。
时间数据
因此,对于您的问题范围,我将尝试简化时间问题,并解释教科书中的指导。简单的规则,同时考虑规范化和时间要求,以及您没有预见到的使用。
首先,为任何类型的 Temporal 列使用正确的数据类型。这意味着 DATETIME 或 SMALLDATETIME,具体取决于您需要的分辨率和范围。如果只需要 DATE 或 TIME 部分,您可以使用它。这允许您直接在 WHERE 子句中使用 SQL 函数执行日期和时间运算。
其次,确保为列和变量使用非常清晰的名称。
有三种类型的时态数据。这一切都是为了正确分类,以便治疗(计划内和计划外)很容易(这就是为什么你的问题是一个好问题,为什么我会提供完整的解释)。优点是使用内联日期/时间函数的 SQL 更简单(您不需要计划的 Temporal SQL 函数)。始终存储:
即时为 SMALL/DATETIME,例如。更新Dtm
Interval 为 INTEGER,明确标识列名中的 Unit,例如。 IntervalSec 或 NumDays
有些技术人员认为间隔应该存储在 DATETIME 中,而不管使用的组件是什么,例如自 1900 年 1 月 1 日午夜以来的秒数或月数等。这很好,但需要更笨重(不复杂) 代码在初始存储和提取时都存在。
无论你选择什么,都要保持一致。
期间或持续时间。这被定义为两个单独的瞬间之间的时间段。存储取决于句点是合还是不合。
对于联合时段,根据您的活动要求:为EventDateTime 使用一个SMALL/DATETIME; Period的结尾可以从下一行的Period的开头推导出来,不应存储EndDateTime。
对于分离期,中间有间隔,是的,您需要 2 x SMALL/DATETIME,例如。 RentedFrom 和 RentedTo。如果在同一行。
跨行的期间或持续时间只需要将结束的 Instant 存储在其他行中。 ExerciseStart 是X1 Event 行的Event.DateTime,ExerciseEnd 是X9 Event 行的Event.DateTime。
因此存储为间隔的 Period 或 Duration 完全不正确,不受意见。
数据复制
另外,在规范化数据库中,即。其中EndDateTime 没有被存储(除非不相交,如上所述),存储一个可以派生的数据将引入一个更新异常而没有。
有一个EndDateTime,你在一个地方就有了一个真相的版本;与重复数据一样,您在另一列中有第二个版本的事实:
破坏 1NF
这两个事实需要以事务方式一起维护(更新),并且存在不同步的风险
由于事实的两个版本,不同的查询可能会产生不同的结果
通过维护科学很容易避免所有这些。回报(单次查询速度提升微不足道)不值得破坏数据的完整性。
您能否稍微扩展一下 conjunct 和 disjunct 之间的实际区别以及这些概念对数据库设计的直接实际影响? (据我了解,我的数据库中的 exercise 和 temp-basal 是分离的,因为它们是由空格分隔的不同事件。而 basal 本身是结合的,因为总是有一个值)
不完全是。在您的数据库中(据我所知):
所有事件都是瞬间,不结合或不结合时期
Exercise 和 TempBasal 除外,它们存储了结尾的 Instant,因此它们有句点,句点之间有空格;因此它们是分离的。
我认为您想确定更多的持续时间,例如 ActiveInsulinPeriod 和 ActiveCarbPeriod 等,但到目前为止,它们只有一个事件(即时)是导致的。
我不认为你有任何联合时期(很可能有,但我很难确定任何时期。我收回我所说的(当它们是读数时,它们看起来是联合的,但我们已经取得了进展)。
关于连词句的简单例子,我们可以使用实际效果,请参考this time-series question。文本和代码可能很有价值,所以我已经链接了 Q/A,但我特别希望你看看数据模型。忽略这三个实现选项,它们与此上下文无关。
该数据库中的每个时期都是联合。产品始终处于某种状态。任何 Period 的 End-DateTime 是 Product 下一个 行 的 Start-DateTime。
【讨论】:
这完全取决于您想对数据做什么。正如您所说,如果您存储它,您可以按结束时间过滤。另一方面,如果您想找到“所有持续时间超过一个小时的事件”,那么持续时间将是最有用的。
当然,如果需要,您可以随时存储两者。
重要的是:您知道要如何使用这些数据吗?
编辑:只是为了添加更多内容,根据您使用的数据库,您可能希望考虑使用视图:仅存储(例如)开始时间和持续时间,但有一个公开开始的视图时间、持续时间和计算的结束时间。如果您需要查询所有三列(无论是一起还是单独),您需要检查您的数据库对索引视图列的支持。这具有方便和清晰的好处,但没有数据冗余的缺点(必须保持“备用”列与其他两个列同步)。另一方面,它更复杂,需要您的数据库提供更多支持。
【讨论】:
结束 - 开始 = 持续时间。
有人可能会争辩说,您甚至可以使用 End 和 Duration,因此任何组合都没有区别。
除了你需要the column included to filter on it的琐碎,所以包括
【讨论】: