【发布时间】:2015-02-26 23:39:51
【问题描述】:
我正在为我的数据仓库中的时间构建一个时间维度。我已经有了日期维度。
如何表示未知时间?在我的 DimDate 维度中,我将 01/01/1753 标记为为未知日期保留,但我认为时间会有点困难。我们不允许在事实表中使用 NULL。我该怎么做?那一行会是什么样子?
【问题讨论】:
标签: time data-warehouse dimensional-modeling
我正在为我的数据仓库中的时间构建一个时间维度。我已经有了日期维度。
如何表示未知时间?在我的 DimDate 维度中,我将 01/01/1753 标记为为未知日期保留,但我认为时间会有点困难。我们不允许在事实表中使用 NULL。我该怎么做?那一行会是什么样子?
【问题讨论】:
标签: time data-warehouse dimensional-modeling
您说“我们不允许在事实表中使用 NULL”,但问“我如何表示未知时间?”
假设您在 FACT 表中使用数据类型 TIME + 对来自源系统的数据强制执行 NOT NULL 约束 => 您根本无法在事实中插入未知\无效时间,因此应该没有问题。
上述的明显例外是源系统报告的无效业务明智值,例如Sunil建议('00:59:59.9999999')但这是非常罕见的,由于显而易见的原因不稳定的解决方案(更改需求可能轻松将此值转换为有效值)
如果您选择允许(我希望您这样做)来自源系统的具有 NULL 值或无效日期的记录输入事实,那么最佳做法是在我们的 DimTime 上使用代理键并将它们作为 FK 插入您的 FACT表格 - 这将很容易让您在维度中表示有效 + 无效值。 这种方法还可以轻松支持无效的业务明智值 ('00:59:59.9999999') 的方法,这样的值会获得 FK_DimTime=-1。
我强烈建议允许来自源系统的特定类型的垃圾进入 FACT(即 - 无效\缺失\NULL 日期\时间值)表,只要您在相关的 DIM 中清楚地标记它,因为这往往会促使用户提高源系统中的数据质量。
这里有一些关于这个问题的背景 https://www.kimballgroup.com/1997/07/its-time-for-time/ https://www.kimballgroup.com/2004/02/design-tip-51-latest-thinking-on-time-dimension-tables/
【讨论】:
它可以看起来像你想要的任何东西。大多数维度都有某种“显示名称”,因此您的维度可能如下所示:
create table dbo.DimDate (DateID int, DateValue date, DisplayDate nvarchar(20))
go
-- this is an unknown date; 1753-01-01 is only there because we need some valid date value
insert into dbo.DimDate values (1, '1753-01-01', 'Unknown')
go
-- this is the real date 1 Jan 1753
insert into dbo.DimDate values (2, '1753-01-01', '01 Jan 1753')
go
create table dbo.DimTime (TimeID int, TimeValue time, DisplayTime nvarchar(20))
go
-- this is an unknown time; 00:00 is only there because we need some valid time value
insert into dbo.DimTime values (1, '00:00', 'Unknown')
go
-- this is the real time value for midnight
insert into dbo.DimTime values (2, '00:00', 'Midnight')
go
当然,这假设您的报告工具和用户使用 DisplayDate 和 DisplayTime 列进行过滤,而不是直接使用 DateValue 和 TimeValue 列,但这只是培训和标准等问题无论如何,您采用的解决方案都需要被理解。
还有其他替代方法,例如未知值的标志列,或负TimeID 表示未知值的约定。但在我看来,与显式行值相比,这些值不太明显且更难维护。
【讨论】:
只需使用-1 技术代理键创建DimTime 记录,然后将值“00:59:59.9999999”填充到时间列。这样一来,您的 DWH 将不太可能捕获时间(精确到最后一位数字),当您想要放置过滤器时,它将始终等同于您的报告或查询中的未知数,
EventTime < @ReportTime AND EventTime <> '00:59:59.9999999'
希望这是解决您问题的可行方法。
【讨论】: