作为报告设置的一部分,我有一个SQL查询来获取每周下达的订单数量:
select datepart(isowk, order_date), count(*)
from orders where year(order_date) = @Year
group by datepart(isowk, order_date), year(order_date)
order by 1
请注意,我在isowk
函数调用中使用了新的datepart
格式,因为丹麦的商家通常使用ISO周数。
使用@Year = 2010
运行此查询会产生一个结果集simialar:
1 5
2 7
3 10
...
53 3
你和我都知道2010年还没有结束,当然还没有第53周。实际上,有一年 - 前三天属于ISO 2009年第53周。尽管可能向其他程序员解释这一点,但是想要阅读我的报告的人永远不会理解这一点。因此,我希望通过将数据“移动”到2009年来摆脱本周53.
如何重写我的WHERE
子句,将数据集过滤为定义为@Year
的第1周的星期一和上周的星期五(52或53)之间的订单?< / p>
答案 0 :(得分:2)
事实上,我不知道任何提供isoyear的编程语言......
create function isoyear(@date datetime) returns smallint as begin
declare @isoyear smallint =
case
when datepart(isowk, @date) = 1 and month(@date) = 12
then year(@date)+1
when datepart(isowk, @date) = 53 and month(@date) = 1
then year(@date)-1
else year(@date)
end;
return @isoyear;
end;
希望下次我们能得到一个datepart(isoyear,......)......
答案 1 :(得分:1)
你可以试试这个:
set datefirst 1;
declare @Year smallint = 2010;
declare @DayInFirstWeek datetime = cast(@Year as varchar)+'0104';
declare @FirstDayInFirstWeek datetime =
@DayInFirstWeek - datepart(dw,@DayInFirstWeek)+1
declare @DayInFirstWeekNextYear datetime = cast(@Year+1 as varchar)+'0104';
declare @LastDayInLastWeek datetime =
@DayInFirstWeekNextYear - datepart(dw,@DayInFirstWeekNextYear);
select datepart(isowk, order_date), count(*)
from orders
where order_date between @FirstDayInFirstWeek and @LastDayInLastWeek
group by datepart(isowk, order_date)
order by 1;
如果您一周的第一天不是星期一,那么它可能无效!
答案 2 :(得分:0)
执行IF语句 - 我不保证SQL服务器语法,但是:
// IF ISO week is 53, return week 1 of next year.
GROUP BY IF(datepart(isowk, order_date)) = 53,
CONCAT("1/", year(order_date) + 1),
CONCAT(datepart(isowk, order_date), "/", year(order_date))
答案 3 :(得分:0)
我将使用我对Manfred's answer的评论中描述的方法自行尝试。我们的想法是找到指定年份和第一年的第一个ISO周的第一天,允许对输入记录进行索引启用between
过滤。
首先,我创建一个函数,它将找到特定年份第一个ISO周的第一天:
create function firstIsoDay(@year int) returns datetime as begin
declare @first datetime
select @first = cast(cast(@year as char(4)) as datetime)
select @first = dateadd(ww, datediff(ww, 0, @first), 0)
if datepart(isowk, @first) > 1 set @first = @first + 7
return @first
end
免责声明:此功能未经测试(目前没有可用的Sql Server 2008)。
然后可以在between
过滤器中使用此函数的两次调用来进行实际数据查询:
select datepart(isowk, order_date), count(*) from orders
where order_date between firstIsoDay(@Year) and firstIsoDay(@Year + 1)
group by datepart(isowk, order_date), year(order_date)
order by 1
请记住,between
是双向的。如果order_date
中的值包含截断日期(没有时间),则应将-1
添加到where
子句的末尾。在我的用例中,order_date
包含日期和时间,所以在午夜的两个日期之间应该没问题。
答案 4 :(得分:0)
这里只是说出基本答案:
如果您根据ISO周查询,必须根据ISO年度(而非日历年)进行过滤
如何为您的数据(或where子句)添加ISO年份列与其他人描述的一样。