【问题标题】:Modification todate dimension in SQL ServerSQL Server 中的修改日期维度
【发布时间】:2017-04-04 23:12:14
【问题描述】:

我需要一个关于我在 SQL Server 的日期维度中创建的列之一的建议,基本上是滚动几周..

我的数据仓库中有一张表dimDate

我想在dimdate 表中创建一个列,该列将包含任何一年的周数,并且每周应该有 7 天。

例如:2015 年有 53 周,但第 53 周只有 5 天(因为我猜在 SQL Server 中该周从星期日开始)。

我想从 2016 年开始再增加 2 天(2016 年 1 月 1 日和 2 日),以用 7 天完成第 53 周,并且 2016 年的第 1 周应该从 2016 年 1 月 3 日开始,依此类推。

如果有任何建议可以很好地开始。

【问题讨论】:

  • 您几乎已经回答了自己的问题:“在 dimdate 中创建一个列,其中包含任何年份的周数”。你这样做了吗?一旦你写了正确的更新语句
  • 我有 weekofyear 列,但是到第 53 周只有 5 天,我正在考虑一个合适的更新脚本,不确定它可能是什么。
  • 这是业务事先手动决定的,还是这里有硬性规定?规则是什么 - 是否每周有 7 天,即使延长到明年?有没有不应该的情况?即如果第 53 周只有一天?要编写脚本,您需要明确的规则。脚本的第一部分是识别每年最后一周的数字 - 从一个选择开始。
  • 是的,业务应该事先决定,不幸的是,在这种情况下,你是对的,规则是每周必须有 7 天,即使它延长到明年和第一周明年应该再次从 1 开始。如果第 53 周有 1 天,那么它必须在明年的前 6 天,所以基本上明年的第一周从 7 日开始。
  • 如果它是自动规则(不是手动业务规则),那么请务必使用脚本。假设您已经有一个部分填充的周数,起点是找到每年的最后一周并计算它有多少天:select year, max(weeknumber) wn from dimdate group by year

标签: sql sql-server-2005


【解决方案1】:

假设您已经填充了几周(但没有延长到下一年),并对列名做出一些假设

此查询查找一年中的最后一周(几乎总是 53,但不要指望它:) 以及它结束的日期

SELECT YearNo, MAX(Week) As Week, MAX(DateKey) As DateKey 
FROM dimDate
GROUP BY YearNo

此查询查找所有短于 7 天的周,以及需要多少天才能使它们变为 7 天。

SELECT 
YearNo, 
Week, 
7-COUNT(DISTINCT DateKey) As ExtraDaysRequired
FROM dimDate
GROUP BY YearNo, Week
HAVING COUNT(DISTINCT DateKey) < 7

这可能总是是一年中的最后一周,但我们不要做任何假设。

让我们结合这些来找出所有最后一周少于 7 天的时间,并加上所需的天数:

SELECT 
Under7Days.YearNo, Under7Days.Week, Under7Days.ExtraDaysRequired,
FinalWeeks.DateKey StartDate, 
DATEADD(d,Under7Days.ExtraDaysRequired,FinalWeeks.DateKey) EndDate
FROM
(
SELECT YearNo, MAX(Week) As Week, MAX(DateKey) As DateKey 
FROM dimDate
GROUP BY YearNo
) As FinalWeeks
INNER JOIN
(
SELECT YearNo, Week, 7-COUNT(DISTINCT DateKey) As ExtraDaysRequired
FROM dimDate
GROUP BY YearNo, Week
HAVING COUNT(DISTINCT DateKey) < 7
) As Under7Days
ON  FinalWeeks.Week = Under7Days.Week
AND FinalWeeks.YearNo = Under7Days.YearNo

所以我们有一个查询来标识需要更新到的开始日期和结束日期以及周数。所以现在我们运行更新:

UPDATE TGT
SET Week = SRC.Week
FROM dimDate TGT
INNER JOIN
(
SELECT 
Under7Days.YearNo, Under7Days.Week, Under7Days.ExtraDaysRequired,
FinalWeeks.DateKey StartDate, 
DATEADD(d,Under7Days.ExtraDaysRequired,FinalWeeks.DateKey) EndDate
FROM
(
SELECT YearNo, MAX(Week) As Week, MAX(DateKey) As DateKey 
FROM dimDate
GROUP BY YearNo
) As FinalWeeks
INNER JOIN
(
SELECT YearNo, Week, 7-COUNT(DISTINCT DateKey) As ExtraDaysRequired
FROM dimDate
GROUP BY YearNo, Week
HAVING COUNT(DISTINCT DateKey) < 7
) As Under7Days
ON  FinalWeeks.Week = Under7Days.Week
AND FinalWeeks.YearNo = Under7Days.YearNo
) SRC
ON TGT.DateID BETWEEN SRC.StartDate AND SRC.EndDate

看起来很复杂?有六种方法可以编写相同的内容,但这种方法是循序渐进的。您可能可以编写一个窗口函数来做同样的事情,但我把它留给其他人练习。

【讨论】:

  • 我的维度表中有另一列使用它,我得到了与您提供的相同的解决方案。您的解决方案是一项了不起的工作,但是在第 53 周更新声明之后这里只有一个问题似乎有 7 天,但之后明年的第一周从第 2 周开始,我的解决方案也有同样的问题。我检查了我的解决方案,它与您的解决方案几乎相同,但步骤更多,但知道如何解决更新后的dimdate缺少第一周的问题吗?更新似乎更新了第 1 周,这就是为什么会丢失明年的第 1 周。
  • 所以基本上无论您用来获取周数(我猜是日期部分)都已经为您解决了 - 几乎总是需要将第 1 周设置为前一年的最后一周?所以他可以做不同的事情。只需从所有周中减去 1,然后将第 0 周设置为前一周。
  • 对不起,你是什么意思?可能无法理解您的修复,但我想说的是,只要第 53 周没有在星期六结束,它就会错过第一周和第 1 周 =2。仍然是一个错误。
  • 如果您在应用任何脚本之前查看现有数据,您是否注意到第 1 周始终是您需要添加的额外天数(除非第 1 周 = 7天)?这将是一种更简单的方法。 (我假设你已经用一些东西填充了一周)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多