在我的日期维度 Table 中创建一个列的 SQL 语法是什么,它将日期分组到这个特定的周分组中?
What is the SQL syntax to create a column in my Date Dimension Table that will group the dates into this specific week grouping?
我正在使用 SQL Server 2014,我有一个日期维度 table(称为 DateDimension),其中一列是日期列(称为日期)。 table 列出从 2000-01-01 到 2017-12-31
的所有日期
从 DateDimension 中提取日期列 Table:
2000-01-01 00:00:00.000
2000-01-02 00:00:00.000
.......................
2017-12-31 00:00:00.000
我需要一个新列(比如 "Week Group"),其中 table 将使用以下逻辑对上述日期进行分组:
一周从星期一开始,到星期日结束。
因此,对于 2000 年 1 月 3 日(星期一)和 2000 年 1 月 9 日(星期日)之间的日期,新列将列出 "Wk 03-09 January 2015",依此类推日期维度中的剩余日期 Table.
实现这个的 T-SQL 代码是什么?
我假设你的 @@datefirst
对应星期天。而且我还假设文本的年月部分对应于一周的开始日而不是结束日。
您可以在 update
中使用第一个表达式,甚至可以将其用作计算列、函数或视图。由于区域设置,我不记得哪些日期函数存在确定性问题,因此可能存在一些限制。
concat(
'Wk ',
right('0' + datename(day, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")), 2),
'-',
right('0' + datename(day, dateadd(day, -((datepart(weekday, "Date") + 5) % 7)+6, "Date")),2),
' ',
datename(month, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")),
' ',
datename(year, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"))
)
由于计算中涉及两个日期,因此您无法轻松使用 format()
函数。这是完成同样事情的 two-step update
:
update DateDimension
set WeekGroup =
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
);
update DateDimension
set WeekGroup =
replace(
WeekGroup,
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
);
如果您喜欢嵌套表达式,当然可以一步完成:
update DateDimension
set WeekGroup =
replace(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
),
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
);
数学真的没那么复杂:
要找到每个日期的 "week" 开始时间,我们要确定自上周一以来的天数。星期一被算作第 2 周的第 2 天(当 @@datefirst
设置为星期日时)所以我们想从 "regular" 工作日编号中减去两个并让它绕到前一周。为避免 mod 元算术中出现负数,只需加 5(与 -2 mod 7 等价)。重复使用相同的表达式来计算所有不同的日期部分。
编辑:在评论中,您已经暗示您确实需要为跨越一个月(也可能包括年)的几周使用稍微不同的格式。
这可以用 case
表达式处理。希望您已经了解了总体思路,并且可以看到在何处对您希望在两种情况下应用的格式进行调整。
update DateDimension
set WeekGroup =
case
when month(dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")) =
month(dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"))
then
replace(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
),
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
)
else
concat(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd MMMM yyyy-'
),
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd MMMM yyyy'
)
)
end;
我正在使用 SQL Server 2014,我有一个日期维度 table(称为 DateDimension),其中一列是日期列(称为日期)。 table 列出从 2000-01-01 到 2017-12-31
的所有日期从 DateDimension 中提取日期列 Table:
2000-01-01 00:00:00.000
2000-01-02 00:00:00.000
.......................
2017-12-31 00:00:00.000
我需要一个新列(比如 "Week Group"),其中 table 将使用以下逻辑对上述日期进行分组:
一周从星期一开始,到星期日结束。 因此,对于 2000 年 1 月 3 日(星期一)和 2000 年 1 月 9 日(星期日)之间的日期,新列将列出 "Wk 03-09 January 2015",依此类推日期维度中的剩余日期 Table.
实现这个的 T-SQL 代码是什么?
我假设你的 @@datefirst
对应星期天。而且我还假设文本的年月部分对应于一周的开始日而不是结束日。
您可以在 update
中使用第一个表达式,甚至可以将其用作计算列、函数或视图。由于区域设置,我不记得哪些日期函数存在确定性问题,因此可能存在一些限制。
concat(
'Wk ',
right('0' + datename(day, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")), 2),
'-',
right('0' + datename(day, dateadd(day, -((datepart(weekday, "Date") + 5) % 7)+6, "Date")),2),
' ',
datename(month, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")),
' ',
datename(year, dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"))
)
由于计算中涉及两个日期,因此您无法轻松使用 format()
函数。这是完成同样事情的 two-step update
:
update DateDimension
set WeekGroup =
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
);
update DateDimension
set WeekGroup =
replace(
WeekGroup,
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
);
如果您喜欢嵌套表达式,当然可以一步完成:
update DateDimension
set WeekGroup =
replace(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
),
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
);
数学真的没那么复杂:
要找到每个日期的 "week" 开始时间,我们要确定自上周一以来的天数。星期一被算作第 2 周的第 2 天(当 @@datefirst
设置为星期日时)所以我们想从 "regular" 工作日编号中减去两个并让它绕到前一周。为避免 mod 元算术中出现负数,只需加 5(与 -2 mod 7 等价)。重复使用相同的表达式来计算所有不同的日期部分。
编辑:在评论中,您已经暗示您确实需要为跨越一个月(也可能包括年)的几周使用稍微不同的格式。
这可以用 case
表达式处理。希望您已经了解了总体思路,并且可以看到在何处对您希望在两种情况下应用的格式进行调整。
update DateDimension
set WeekGroup =
case
when month(dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date")) =
month(dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"))
then
replace(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd-XX MMMM yyyy' /* leave a placeholder */
),
'XX',
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd'
)
)
else
concat(
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7), "Date"),
'Wk dd MMMM yyyy-'
),
format(
dateadd(day, -((datepart(weekday, "Date") + 5) % 7) + 6, "Date"),
'dd MMMM yyyy'
)
)
end;