【问题标题】:Temporal Tables and Time Dimension in SQL Data Warehouse and TableauSQL 数据仓库和 Tableau 中的时态表和时间维度
【发布时间】:2020-10-08 14:14:58
【问题描述】:

我正处于重新设计我们的数据仓库的初期阶段,发现时态表是一种非常棒的 SCD 类型 4 方法。数据仓库的这个迭代将具有日期维度,以便我们可以进入时间点使用业务逻辑进行比较(例如比较财政季度中的特定日期)。日期维度将具有各种酷的业务时间标记,例如财政年度/季度/月和月/季度/年中的日期,以及各种其他开始和结束日期标志,指示不同的业务流程和“季节”。

我看到的唯一问题是,我看不到如何在查询中利用日期维度,而不总是使用单独的日期字段并将查询作为“for system_time all”执行。这是因为您无法对 'for system_time' 语句之后的日期进行任何操作。

现在我知道您可以看到日期是一个变量,并且您可以在设置变量时进行操作。我遇到的问题是 Tableau 不允许您执行 sql 脚本(就像 power BI 一样),只能执行单个语句。所以,我不能有一个我们根据查询结果将日期设置为变量的场景。因此,我不确定如何运行时间查询来让我们获取特定财政季度的这一特定日期的值。希望这是有道理的。

如果我必须使用触发器手动创建历史表,我会这样做,但我认为我的谷歌搜索尚未找到更好的解决方案。有什么想法或文章可以指点我吗?


编辑添加示例:

例如,假设我们有一个包含几个字段的日期维度 (dateTable):

date
fiscalYear
fiscalDayOfYear

现在假设我有一个包含几个字段的表 (statusTable):

userid
status
date (FK to date dimension)

现在假设我想比较 2019 和 2020 财年第 20 天的特定用户状态。如果不使用临时表,它看起来像:

select st.userid, st.status from statusTable st inner join dateTable dt on st.date = dt.date where dt.fiscalDayOfYear = '20' AND (dt.fiscalYear = '2020' or dt.fiscalYear = '2019')

现在如果 statusTable 是一个临时表,它会变成这样:

userid
status
systemtimeFrom (generated by temporal table)
systemtimeTo (generated by temporal table)

我将如何使用时态表执行上述查询中的操作?除了系统时间字段之外,我还看到人们将字段“日期”放入状态表的示例。它们具有自动生成的值。因此,理论上,我可以像在上面的查询中那样加入。我看到的问题是,如果我在没有时间约束的情况下查询临时表,它只会查看最新状态(因为这就是表中的全部内容)。如果我想包含历史和当前表,我想我需要做一个包含“FOR SYSTEM_TIME ALL”的选择,我觉得这消除了时态表的好处(因为你不能做很酷的时间切片时态查询)。

我想知道是否有一种方法可以使用我不知道的某种魔法对时态表进行上述查询。我希望能够做类似的事情(我知道这不是有效的 SQL,因为您只能在 as of 子句中提供日期或变量):

select st.userid, st.status from statusTablest st for system_time as of (select date from datetable where dt.fiscalDayOfYear = '20' AND (dt.fiscalYear = '2020' or dt.fiscalYear = '2019'))

抱歉,我知道这不是一个很好的例子。我没有太多的例子,因为我是从头开始设计的。我希望我能得到我想要做的事情。如果不是,请告诉我,我可以尝试用不同的方式说出来。

【问题讨论】:

  • “获取特定会计季度这一特定日期的值”:因此您在“会计季度”='x' 和“会计季度日”= n 上过滤您的日期维度。看起来很简单,这表明我可能误解了你的问题 - 你能澄清一下吗?
  • 所以时间切片的工作方式是,您需要获取所有记录(当前+历史记录)才能正常工作,不是吗?否则 "Fiscal Quarter" = 'x' 和 "Day of Fiscal Quarter" = n 将仅应用于当前表而忽略历史记录。我对它的理解可能是错误的。这有助于澄清吗?
  • 我认为这个链接解释了如何使用临时表而不是更标准的 SCD2 表:docs.microsoft.com/en-us/sql/relational-databases/tables/… 如果这个链接不能回答你的问题,请你解释一下(用例子)你想要什么查询您期望的数据和结果?
  • 感谢您的回复。它没有回答我的问题,因为它不使用时间维度。我没有例子,因为我还没有这样做。让我试着想点什么,我会再回复的。
  • 我编辑了我的问题以包含一个示例。感谢@NickW 为您(或任何人)提供的任何帮助!

标签: tsql tableau-api data-warehouse temporal-tables


【解决方案1】:

感谢您提供的示例和其他信息。我意识到试图为这类问题想出一个真实世界的例子绝非易事,但我需要指出你的例子与维度模型不兼容,因为你永远不会像那样将维度连接在一起并使用一个维度过滤另一个 - 维度连接到并用于过滤事实表。

但是,在说明了这一警告后,看看你的例子......

您显示的非临时表不支持您要运行的查询类型,因为它需要您可能要查询的每个日期/用户/状态组合的记录 - 这显然是不支持。相反,您需要有效的开始日期和结束日期来显示每个用户 ID 和状态组合适用的日期期间。如果您有这些日期,那么您的查询可能看起来像这样(一个未经测试的示例,因为我没有数据可以运行它):

select st.userid, st.status, st.ValidFrom, st.ValidTo 
from statusTable st 
inner join dateTable dt1 on st.ValidFrom = dt1.date 
inner join dateTable dt2 on st.ValidTo = dt2.date 
where 
(dt1.fiscalDayOfYear <= '20' AND dt2.fiscalDayOfYear >= '20') -- your fiscal day is within the coverage of the statusTable record
AND
(dt1.fiscalYear = '2020' or dt1.fiscalYear = '2019') -- limit to the 2 years in question
AND
(dt1.fiscalYear = dt2.fiscalYear); -- Attempt to filter to a single record.Probably incorrect if the ValidFrom and ValidTo dates for a record are in different years; required logic more complex than this 

所以你基本上必须有一个 SCD2 类型的表才能运行这些类型的查询。

临时表也有 ValidFrom 和 ValidTo 列 - 因此它与传统的 SCD2 表基本相同;不同之处在于 SCD2 表必须使用 ETL 逻辑维护,而临时表由数据库引擎自动维护。

查询 SCD2 表和等效时态表的逻辑几乎相同。主要区别在于使用

FOR SYSTEM_TIME ...

clause - 但是这一切要做的就是从查询中使用的状态表中提取数据子集,并且要做到这一点,您需要能够构造并将合适的开始和结束日期参数传递给查询。如果您不能这样做(或者时间段太长以至于生成子集不太可能使查询受益),那么您只需使用:

FOR SYSTEM_TIME ALL

希望澄清/回答您提出的一些观点:

  • 临时表是一种自动存储历史记录的方式,而不必手动维护 SCD2 表 - 但最终结果实际上是相同的
  • 您的声明“我认为我需要执行一个包含“FOR SYSTEM_TIME ALL”的选择,我认为这会消除临时表的好处(因为您不能对时间查询进行很酷的时间切片)。" 表示对临时表的点可能存在误解。它们的好处是它们自动保存历史记录并允许您查询它。 “酷时间切片时态查询”是由您的日期维度启用的,而不是由您的时态表启用的,因此您仍然需要将您的时态表连接到日期维度才能使其正常工作

【讨论】:

  • 感谢您的回复。抱歉造成误解,状态表应该是事实表。我只是想把相关信息放在那里。它将状态映射到用户(在这个虚构的表中)。我知道我不善于解释自己! (这就是我进入 IT 而不是教学的原因)。是的,我意识到它不会对每一行都有记录。在开会时,我想不出更好的例子。我只是想显示我正在考虑的查询类型。
  • "“酷时间切片时态查询”是由您的日期维度启用的,而不是由您的时态表启用的,因此您仍然需要将您的时态表连接到日期维度才能得到这个工作”——我想就是这样。这导致我不使用时态表,因为我的最终用户(数据分析)了解数据但根本不是技术人员。如果我给他们两种分割数据的方法,那将会造成混乱并导致问题。 (一个按日期暗淡,一个按时间查询)。我还认为 UTC 对他们来说是一个挑战。谢谢你的信息,我很感激。
  • 我的最后(!)评论:如果您需要能够通过事实发生时适用的属性而不是这些属性的当前值来对事实进行切片和切块,那么您需要实现 SCD2 表。一旦您做出决定,您就可以选择传统的 SCD2 表或使用临时表:它们是实现相同目的的两种选择。使用 Date Dim 和使用临时表不是同一问题的两种替代解决方案 - 它们是用于不同目的的不同类型的对象。
  • SCD 表非常常见,大多数最终用户都可以毫无问题地处理它们;如果存在复杂性,那么您应该通过视图、配置 BI 工具的方式等向最终用户隐藏它们。
  • 谢谢 NickW,是的,我们应该隐藏它们,我同意。问题是人手太少(一个常见的问题),当我搞定所有这些时,我就会退休了。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-25
相关资源
最近更新 更多