仅按日期缓慢改变维度
Posted
技术标签:
【中文标题】仅按日期缓慢改变维度【英文标题】:Slowly changing dimension by date only 【发布时间】:2014-12-11 08:29:19 【问题描述】:我有一个数据库表,它使用渐变维度的数据仓库概念来跟踪旧版本。 所以,我用Log Trigger机制实现了它。
我的桌子是这样的:
CREATE TABLE "T_MyTable" (
"Id" INT NOT NULL DEFAULT NULL,
"Description" NVARCHAR(255) NULL DEFAULT NULL )
我创建了一个 hystory 表
CREATE TABLE "T_MyTableHistory" (
"Id" INT NOT NULL DEFAULT NULL,
"Description" NVARCHAR(255) NULL DEFAULT NULL,
StartDate DATETIME,
EndDate DATETIME )
然后,通过这样的触发器,我得到了历史记录:
CREATE TRIGGER TableTrigger ON T_MyTable FOR DELETE, INSERT, UPDATE AS
DECLARE @NOW DATETIME
SET @NOW = CURRENT_TIMESTAMP
UPDATE T_MyTableHistory
SET EndDate = @now
FROM T_MyTableHistory, DELETED
WHERE T_MyTableHistory.Id = DELETED.Id
AND T_MyTableHistory.EndDate IS NULL
INSERT INTO T_MyTableHistory (Id, Description, StartDate, EndDate)
SELECT Id, Description, @NOW, NULL
FROM INSERTED
而且,为了查询历史表,我使用
SELECT Id, Description
FROM T_MyTableHistory
WHERE @DATE >= StartDate
AND (@DATE < EndDate OR EndDate IS NULL)
现在,我的问题是:我的客户实际上会按 date only(即没有一天中的时间)查询历史记录表,因此我需要获取该日期的记录版本。 我想了两个选择:
将触发器(如何?)更改为每个日期只记录一个“历史”记录。
保持触发器不变,记录数据库中的所有变化(包括日期和时间),然后查询历史表以获取特定日期的最新版本(如何?)
我的感觉是第二个选项更容易实现,否则触发器可能会变得复杂(插入或更新,取决于当前日期的历史记录的存在)。
在选择正确的方向时我需要一些帮助,并且我想在所选选项中提供所需的 SQL 查询示例。
【问题讨论】:
【参考方案1】:我同意您的第二意见。
最好将日期与时间一起保存。根据日期使用过滤数据时
CONVERT()
函数确保仅比较 DATE。此外,当客户输入单个日期时,如果记录具有相同的开始日期和结束日期
它们不会出现在您的过滤器中,因此使用 Date >= StartDate 和 Date = ,
DECLARE @Date AS DATETIME
SET @Date = '2013-07-30'
SELECT TOP 1 Id, Description
FROM T_MyTableHistory
WHERE CONVERT(VARCHAR(20), @DATE, 103)
>= CONVERT(VARCHAR(20), StartDate, 103)
AND (CONVERT(VARCHAR(20), @DATE, 103)
< CONVERT(VARCHAR(20), EndDate, 103) OR EndDate IS NULL)
ORDER BY StartDate DESC
【讨论】:
感谢您的回答。实际上,如果我在同一天(不同时间)有多个版本,通过您的查询,我会收到许多相同 ID 的记录,对吗?我想要的是在指定日期有效的最新记录。 简单,第一条记录使用TOP 1,数据排序使用ORDER BY StartDate DESC。试试我更新的答案。【参考方案2】:最后,我想出了这个查询:
SELECT Id, Description
FROM T_MyTableHistory
WHERE ( DateAdd(day, datediff(day,0, @MyDate), 0) >= StartDate ) AND
(( DateAdd(day, datediff(day,0, @MyDate), 0) < EndDate ) OR ( EndDate IS NULL ))
这应该比 varchardatetime 转换更快,并且它也应该与语言环境无关。
顺便说一句,这个查询不需要TOP 1
和ORDER BY
子句,因为函数
DateAdd(day, datediff(day,0, @MyDate)
自动返回所选日期,带有“午夜”时间(例如 20141215 00:00:00),因此具有相同日期的记录会自动从结果中剔除。
参考资料:
How to return the date part only from a SQL Server datetime datatype
Best approach to remove time part of datetime in SQL Server
【讨论】:
以上是关于仅按日期缓慢改变维度的主要内容,如果未能解决你的问题,请参考以下文章