1

我在 OLTP 中有下表查找表

CREATE TABLE TransactionState
(
    TransactionStateId INT IDENTITY (1, 1) NOT NULL,
    TransactionStateName VarChar (100)
)

当这进入我的 OLAP 时,我将结构更改如下:

CREATE TABLE TransactionState
(
    TransactionStateId INT NOT NULL, /* not an IDENTITY column in OLAP */
    TransactionStateName VarChar (100) NOT NULL,
    StartDateTime DateTime NOT NULL,
    EndDateTime NULL
)

我的问题是关于 TransactionStateId 列。随着时间的推移,我的 OLAP 中可能有重复的 TransactionStateId 值,但是结合 StartDateTime 和 EndDateTime,它们将是唯一的。

我已经看到了 Type-2 维度的示例,其中添加了 OriginalTransactionStateId 并将传入的 TransactionStateId 映射到它,加上一个新的 TransactionStateId IDENTITY 字段成为 PK 并用于连接。

CREATE TABLE TransactionState
(
    TransactionStateId INT IDENTITY (1, 1) NOT NULL,
    OriginalTransactionStateId INT NOT NULL, /* not an IDENTITY column in OLAP */
    TransactionStateName VarChar (100) NOT NULL,
    StartDateTime DateTime NOT NULL,
    EndDateTime NULL
)

我应该选择 bachellorete #2 还是 bachellorete #3?

4

3 回答 3

2

通过这句话:

与 和 的组合StartDateTimeEndDateTime它们将是独一无二的。

您的意思是它们永远不会重叠或它们满足数据库UNIQUE约束?

如果是前者,那么您可以使用StartDateTimein 连接,但请注意它可能效率低下,因为它将使用"<="条件而不是"=".

如果是后者,那么只需使用假身份即可。

数据库通常不允许对此查询使用有效的算法:

SELECT  *
FROM    TransactionState
WHERE   @value BETWEEN StartDateTime AND EndDateTime

,除非你用SPATIAL数据做神秘的把戏。

这就是为什么你必须在 a 中使用这个条件JOIN

SELECT  *
FROM    factTable
CROSS APPLY
        (
        SELECT  TOP 1 *
        FROM    TransactionState
        WHERE   StartDateTime <= factDateTime
        ORDER BY
                StartDateTime DESC
        )

,这将剥夺优化器使用 的可能性HASH JOIN,这在许多情况下对此类查询最有效。

有关此方法的更多详细信息,请参阅本文:

重写查询以便它可以使用HASH JOIN导致600%性能提升倍数,尽管只有当您的日期时间具有一天或更低的准确性(或者哈希表会变得非常大)时才有可能。

由于您的时间组件被剥离了您的StartDateTimeand EndDateTime,您可以创建一个CTE这样的:

WITH    cal AS
        (
        SELECT CAST('2009-01-01' AS DATE) AS cdate
        UNION ALL
        SELECT DATEADD(day, 1, cdate)
        FROM   cal
        WHERE  cdate <= '2009-03-01'
        ),
        state AS
        (
        SELECT  cdate, ts.*
        FROM    cal
        CROSS APPLY
                (
                SELECT  TOP 1 *
                FROM    TransactionState
                WHERE   StartDateTime <= cdate
                ORDER BY
                        StartDateTime DESC
                ) ts
        WHERE   ts.EndDateTime >= cdate
        )
SELECT  *
FROM    factTable
JOIN    state
ON      cdate = DATE(factDate)

如果您的日期范围跨越多个100日期,请调整MAXRECURSION上的选项CTE

于 2009-07-28T16:54:19.973 回答
1

请注意,这IDENTITY(1,1)是在该列中自动生成值的声明。这与 不同PRIMARY KEY,后者是使列成为主键聚集索引的声明。这两个声明意味着不同的东西,如果你不说PRIMARY KEY.

于 2009-07-28T17:03:45.587 回答
1

您还可以使用 SSIS 加载 DW。在渐变维度(SCD) 转换中,您可以设置如何对待每个属性。如果选择了历史属性,则将类型 2 SCD 应用于整行,并且转换会处理细节。如果您愿意,您还可以配置start_dateend_datecurrent/expired列。

这里要区分的是主键和业务(自然)键之间的区别。主键唯一标识表中的一行。业务键唯一标识一个业务对象/实体,它可以在维度表中重复。每次应用 SCD 2 时,都会插入一个新行,主键是新的,但业务键相同;然后旧行被标记为过期,而新行被标记为当前 - 或者适当地填充开始日期和结束日期字段。

DW不应该暴露主键,所以从OLTP传入的数据中包含业务键,而主键的分配由DW控制;IDENTITY int 适用于维度表中的 PK。

很酷的是 SSIS 中的 SCD 转换可以解决这个问题。

于 2009-11-29T04:50:37.097 回答