查询涉及时间维度的数仓数据
Posted
技术标签:
【中文标题】查询涉及时间维度的数仓数据【英文标题】:Querying a data warehouse data involving time dimension 【发布时间】:2011-08-14 11:26:50 【问题描述】:我有两个时间维度表
日期(每一天的唯一行) 一天中的时间(一天中每一分钟的唯一行)
给定这个模式,如果一个人想要检索过去 X 小时的事实,其中 X 可以是任何大于 0 的数字,查询会是什么样子。
当开始时间和结束时间恰好在一年中的两个不同日子时,事情就开始变得棘手了。
编辑:我的事实表没有时间戳列
【问题讨论】:
您可能会创建一个时间列(使用视图,或“with”,或仅与子查询连接)然后使用它。但是时间命令变化很大,知道你正在使用什么数据库是至关重要的。 我目前正在使用 mysql,但我必须在不久的将来使其至少与 sqlserver、oracle 和 sqllite 一起使用 【参考方案1】:事实表确实具有(并且应该具有)原始时间戳,以避免在一天的边界上发生奇怪的按时间查询。奇怪意味着在 WHERE 子句中有某种复杂的日期时间函数。
在大多数 DW 中,这类查询非常少见,但您似乎将数据流式传输到 DW 并同时使用它进行报告。
所以我建议:
在事实表中引入完整的时间戳。
对于旧记录,从日期和时间键重新创建时间戳。
DW 查询都是关于在 WHERE 子句中没有任何函数,或者如果必须使用函数,请确保它是 SARGABLE。
【讨论】:
【参考方案2】:将Start Date
和End Date
列转换为TIMESTAMP
并填充它们可能会更好。
切片表需要使用适当的interval BETWEEN Start Date AND End Date
。在 Oracle 中,interval
类似于SYSDATE - (4/24)
或SYSDATE - NUMTODSINTERVAL(4, 'HOUR')
这也可以改写为:
Start Date <= (SYSDATE - (4/24)) AND End Date >= (SYSDATE - (4/24))
【讨论】:
【参考方案3】:在我看来,鉴于您拥有的当前架构,您需要从时间维度表中检索符合您的搜索条件的适当时间 ID,然后在事实表中搜索匹配的行。根据您的时间维度的粒度,您可能需要检查执行以下任一操作的性能(SQL Server 示例):
子选择:
SELECT X FOO WHERE TIMEID IN (SELECT ID FROM DIMTIME WHERE HOUR >= DATEPART(HOUR, CURRENT_TIMESTAMP()) 和 DATEID IN (SELECT ID FROM DIMDATE WHERE DATE = GETDATE())
内连接:
SELECT X FOO INNER JOIN DIMTIME ON TIMEID = DIMTIME.ID WHERE HOUR >= DATEPART(HOUR, CURRENT_TIMESTAMP()) INNER JOIN DIMDATE ON DATEID = DIMDATE.ID WHERE DATE = GETDATE()
这些都不是真正有吸引力的选择。
您是否考虑过查询的多维数据集可能用于汇总分析,而不一定用于“最后 X”分析?
如果这不是“汇总”多维数据集,我会同意其他海报的观点,即您应该使用更好的键重新标记事实表,并且如果您确实打算经常搜索下班时间,您可能也应该将其包含在事实表中,因为任何其他尝试都可能使查询不可解析(请参阅What makes a SQL statement sargable?)。
Microsoft 在http://msdn.microsoft.com/en-us/library/aa902672%28v=sql.80%29.aspx 建议:
与其他维度表中使用的代理键相比,日期和时间维度键应该是“智能的”。日期维度的建议键采用“yyyymmdd”形式。这种格式很容易让用户记住并合并到查询中。对于按日期划分为多个表的事实表,它也是推荐的代理键格式。
祝你好运!
【讨论】:
以上是关于查询涉及时间维度的数仓数据的主要内容,如果未能解决你的问题,请参考以下文章