SQL 数据仓库和 Tableau 中的时态表和时间维度
Temporal Tables and Time Dimension in SQL Data Warehouse and Tableau
我正处于重新设计我们的数据仓库的开始阶段,发现时间 tables 是执行 SCD 类型 4 的一种非常棒的方法。数据仓库的这个迭代将具有日期维度,以便我们可以使用业务逻辑进行时间点比较(例如比较财政季度的特定日期)。日期维度将具有各种很酷的业务时间标记,例如财务 year/quarter/month 和日期 month/quarter/year 以及各种其他开始和结束日期标志,表示不同的业务流程和 'seasons'.
我看到的唯一问题是,我看不出如何在不始终使用单独的日期字段并以 'for system_time all' 执行查询的情况下利用查询中的日期维度。这是因为您不能真正对 'for system_time' 语句后的日期进行任何操作。
现在我知道您可以将日期视为变量,并且可以在设置变量时进行操作。我遇到的问题是 Tableau 不允许您执行 sql 脚本(就像 power BI 一样),只能执行单个语句。因此,我无法根据查询结果将日期设置为变量。因此,我不确定如何 运行 一个时间查询来让我们获取特定财政季度特定日期的值。希望这是有道理的。
如果我必须使用触发器手动创建历史 tables,我会这样做,但我认为我的谷歌搜索尚未找到更好的解决方案。您有什么想法或文章可以指点我吗?
编辑添加示例:
例如,假设我们有一个包含几个字段的日期维度 (dateTable):
date
fiscalYear
fiscalDayOfYear
现在假设我有一个包含几个字段的 table (statusTable):
userid
status
date (FK to date dimension)
现在假设我想比较 2019 年和 2020 年财政年度第 20 天的特定用户状态。如果不使用时间 tables,它看起来像:
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 是临时的 table,它看起来会像这样:
userid
status
systemtimeFrom (generated by temporal table)
systemtimeTo (generated by temporal table)
我如何使用时间 table 执行上述查询中的操作?除了系统时间字段之外,我还看到有人将字段 'date' 放入 statusTable 的示例。它们具有自动生成的值。因此,从理论上讲,我可以像在上面的查询中那样加入。我看到的问题是,如果我在没有时间限制的情况下查询时间 table,它只会查看最新状态(因为这就是 table 中的全部内容)。如果我想包括历史和当前 table,我想我需要做一个包含 'FOR SYSTEM_TIME ALL' 的 select,我觉得这会消除时间 tables 的好处(因为你不能做很酷的时间切片时间查询)。
我想知道是否有一种方法可以使用我不知道的某种魔法通过时间 table 执行上述查询。我希望能够做类似的事情(而且我知道这是无效的 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'))
对不起,我知道这不是一个很好的例子。我没有太多示例,因为我是从头开始设计的。我希望我能理解我想做的事情。如果没有,请告诉我,我可以尝试用不同的方式表达。
感谢您提供示例和其他信息。我意识到尝试为这类问题提出一个 real-world 示例绝非易事,但我需要指出您的示例与维度模型不兼容,因为您永远不会像那样将维度连接在一起并使用一个维度过滤另一个维度 - 维度连接并用于过滤事实 tables.
但是,考虑到这个警告,看看你的例子...
您显示的 non-temporal table 不会支持您想要的查询类型 运行 因为它需要为每个 date/user/status 您可能想要查询的组合 - 这显然是不支持的 table。相反,您需要有效的开始日期和结束日期来显示每个用户 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 类型 table 才能 运行 这些类型的查询。
临时 table 也有 ValidFrom 和 ValidTo 列 - 所以它与传统 SCD2 table 基本相同;区别在于 SCD2 table 必须使用 ETL 逻辑维护,而时间 table 由数据库引擎自动维护。
查询 SCD2 table 和等效时间 table 的逻辑几乎相同。主要区别在于
的使用
FOR SYSTEM_TIME ...
子句 - 但所有这一切要做的是对查询中使用的 statusTable 中的数据进行子集化,为此您需要能够构建并传递到查询中,suitable 开始和结束日期参数。如果您不能这样做(或者时间段太长以至于生成子集不太可能对查询有益)那么您只需使用:
FOR SYSTEM_TIME ALL
希望 clarify/answer 您提出的一些观点:
- 时间 tables 是一种自动存储历史的方式,而不是必须手动维护 SCD2 tables - 但最终结果实际上是相同的
- 你的陈述“我想我需要做一个包含 'FOR SYSTEM_TIME ALL' 的 select 我觉得它消除了时间 tables 的好处(因为你无法执行酷时间切片时间查询。”表示可能对时间点 tables 有误解。它们的好处是它们会自动保存历史记录并允许您查询它。 “the cool time slicing temporal queries”是由你的日期维度启用的,而不是由你的时间 tables 启用的,因此你仍然需要加入你的时间 tables 到日期维度以使其正常工作
我正处于重新设计我们的数据仓库的开始阶段,发现时间 tables 是执行 SCD 类型 4 的一种非常棒的方法。数据仓库的这个迭代将具有日期维度,以便我们可以使用业务逻辑进行时间点比较(例如比较财政季度的特定日期)。日期维度将具有各种很酷的业务时间标记,例如财务 year/quarter/month 和日期 month/quarter/year 以及各种其他开始和结束日期标志,表示不同的业务流程和 'seasons'.
我看到的唯一问题是,我看不出如何在不始终使用单独的日期字段并以 'for system_time all' 执行查询的情况下利用查询中的日期维度。这是因为您不能真正对 'for system_time' 语句后的日期进行任何操作。
现在我知道您可以将日期视为变量,并且可以在设置变量时进行操作。我遇到的问题是 Tableau 不允许您执行 sql 脚本(就像 power BI 一样),只能执行单个语句。因此,我无法根据查询结果将日期设置为变量。因此,我不确定如何 运行 一个时间查询来让我们获取特定财政季度特定日期的值。希望这是有道理的。
如果我必须使用触发器手动创建历史 tables,我会这样做,但我认为我的谷歌搜索尚未找到更好的解决方案。您有什么想法或文章可以指点我吗?
编辑添加示例:
例如,假设我们有一个包含几个字段的日期维度 (dateTable):
date
fiscalYear
fiscalDayOfYear
现在假设我有一个包含几个字段的 table (statusTable):
userid
status
date (FK to date dimension)
现在假设我想比较 2019 年和 2020 年财政年度第 20 天的特定用户状态。如果不使用时间 tables,它看起来像:
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 是临时的 table,它看起来会像这样:
userid
status
systemtimeFrom (generated by temporal table)
systemtimeTo (generated by temporal table)
我如何使用时间 table 执行上述查询中的操作?除了系统时间字段之外,我还看到有人将字段 'date' 放入 statusTable 的示例。它们具有自动生成的值。因此,从理论上讲,我可以像在上面的查询中那样加入。我看到的问题是,如果我在没有时间限制的情况下查询时间 table,它只会查看最新状态(因为这就是 table 中的全部内容)。如果我想包括历史和当前 table,我想我需要做一个包含 'FOR SYSTEM_TIME ALL' 的 select,我觉得这会消除时间 tables 的好处(因为你不能做很酷的时间切片时间查询)。
我想知道是否有一种方法可以使用我不知道的某种魔法通过时间 table 执行上述查询。我希望能够做类似的事情(而且我知道这是无效的 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'))
对不起,我知道这不是一个很好的例子。我没有太多示例,因为我是从头开始设计的。我希望我能理解我想做的事情。如果没有,请告诉我,我可以尝试用不同的方式表达。
感谢您提供示例和其他信息。我意识到尝试为这类问题提出一个 real-world 示例绝非易事,但我需要指出您的示例与维度模型不兼容,因为您永远不会像那样将维度连接在一起并使用一个维度过滤另一个维度 - 维度连接并用于过滤事实 tables.
但是,考虑到这个警告,看看你的例子...
您显示的 non-temporal table 不会支持您想要的查询类型 运行 因为它需要为每个 date/user/status 您可能想要查询的组合 - 这显然是不支持的 table。相反,您需要有效的开始日期和结束日期来显示每个用户 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 类型 table 才能 运行 这些类型的查询。
临时 table 也有 ValidFrom 和 ValidTo 列 - 所以它与传统 SCD2 table 基本相同;区别在于 SCD2 table 必须使用 ETL 逻辑维护,而时间 table 由数据库引擎自动维护。
查询 SCD2 table 和等效时间 table 的逻辑几乎相同。主要区别在于
的使用FOR SYSTEM_TIME ...
子句 - 但所有这一切要做的是对查询中使用的 statusTable 中的数据进行子集化,为此您需要能够构建并传递到查询中,suitable 开始和结束日期参数。如果您不能这样做(或者时间段太长以至于生成子集不太可能对查询有益)那么您只需使用:
FOR SYSTEM_TIME ALL
希望 clarify/answer 您提出的一些观点:
- 时间 tables 是一种自动存储历史的方式,而不是必须手动维护 SCD2 tables - 但最终结果实际上是相同的
- 你的陈述“我想我需要做一个包含 'FOR SYSTEM_TIME ALL' 的 select 我觉得它消除了时间 tables 的好处(因为你无法执行酷时间切片时间查询。”表示可能对时间点 tables 有误解。它们的好处是它们会自动保存历史记录并允许您查询它。 “the cool time slicing temporal queries”是由你的日期维度启用的,而不是由你的时间 tables 启用的,因此你仍然需要加入你的时间 tables 到日期维度以使其正常工作