最近我每周都要去统计“华语好声音”和“三个一”活动的一周文章列表。所以在条件语句中,总是少不了限制时间。例如,上周统计“华语好声音”的一个条件子句就是
DATEADD(hour,7, created)>='2018-01-27 00:00:00'
因为系统时间同北京时间相差7小时,所以要用DATEADD()函数把数据库里的created字段时间后移动7小时。
可是,我不想每周统计的时候,都要去看一下日历,看一下最近的周六的日期,因为这样太费时间了,也不是一个真正的程序员应该干的事呀。
于是,我需要根据当前的时间来获取上一个周六的具体时间。
首先,要想办法知道现在是周几。上网,搜了一下,Datepart()这个函数有这个功能。我分别运行了
SELECT Datepart(weekday, getdate())
SELECT Datepart(wk, getdate())
SELECT Datepart(ww, getdate())
SELECT Datepart(weekday, getdate())
SELECT Datepart(dw, getdate())
运行的结果分别是5 6 6 5 5,可是,今天周四。。。。。
肿么回事?肿么办?
于是我各种百度谷歌
最后发现了这么一句
SELECT Datepart(weekday, getdate() +@@DateFirst - 1)
运行了一下,果然显示的是4。但我不会就此罢休的,打破砂锅是必须的!
于是我select @@DateFirst,显示是7。
然后我试了一下
set DateFirst 6
SELECT Datepart(weekday, getdate())
SELECT Datepart(wk, getdate())
SELECT Datepart(ww, getdate())
SELECT Datepart(weekday, getdate())
SELECT Datepart(dw, getdate())
结果变成了 6 6 6 6 6。
再试:
set DateFirst 5
SELECT Datepart(weekday, getdate())
SELECT Datepart(wk, getdate())
SELECT Datepart(ww, getdate())
SELECT Datepart(weekday, getdate())
SELECT Datepart(dw, getdate())
结果变成了 7 6 6 7 7。
set DateFirst 4
SELECT Datepart(weekday, getdate())
SELECT Datepart(wk, getdate())
SELECT Datepart(ww, getdate())
SELECT Datepart(weekday, getdate())
SELECT Datepart(dw, getdate())
结果是 1 7 7 1 1
set DateFirst 3
SELECT Datepart(weekday, getdate())
SELECT Datepart(wk, getdate())
SELECT Datepart(ww, getdate())
SELECT Datepart(weekday, getdate())
SELECT Datepart(dw, getdate())
结果是 2 7 7 2 2
试到这里里就不用再试了, 第一、四、五个查询结果是根据@@DateFirst的值来移动的。当我set DateFirst 4时,第一、四、五个查询结果是1,根据DateFirst字面再理解一下,可以理解了,原来DateFirst是设置每周的第1天是周几。
于是我臭不要脸的试了一下 set DateFirst 0和set DateFirst 8,然后系统果断的回复了我:
Error 2742: SET DATEFIRST 0 is out of range.
Error 2742: SET DATEFIRST 8 is out of range.
验证我的猜测是正确的哈哈哈哈。
继续谷歌百度,原来@@DateFirst这个是设定以周几做为一周的第1天的参数。默认的是周日为第一天。select @@DateFirst,显示果然是7。
wk 和ww这两个参数又是什么鬼呢?于是,我首先设好set DateFirst 1,然后我把这周的日期全试了一下:
SELECT Datepart(wk, '2018-02-05')
SELECT Datepart(ww, '2018-02-05')
SELECT Datepart(wk, '2018-02-06')
SELECT Datepart(ww, '2018-02-06')
SELECT Datepart(wk, '2018-02-07')
SELECT Datepart(ww, '2018-02-07')
SELECT Datepart(wk, '2018-02-08')
SELECT Datepart(ww, '2018-02-08')
SELECT Datepart(wk, '2018-02-09')
SELECT Datepart(ww, '2018-02-09')
SELECT Datepart(wk, '2018-02-10')
SELECT Datepart(ww, '2018-02-10')
SELECT Datepart(wk, '2018-02-11')
SELECT Datepart(ww, '2018-02-11')
结果全是6,继续试:
SELECT Datepart(wk, '2018-02-12')
SELECT Datepart(ww, '2018-02-12')
结果变成了7,我好像有点感觉了。我于是我找了两个特残的日又试了一下
SELECT Datepart(wk, '2018-01-01')
SELECT Datepart(ww, '2018-01-01')
SELECT Datepart(wk, '2017-12-31')
SELECT Datepart(ww, '2017-12-31')
结果显示为1 1 53 53,恍然大悟呀,原来是查询一年的第几周。
一路上遇见的都搞清楚了,继续查询上一个周六的日期。接下来就简单了,把当前的日期减掉从周六度过的日子就行了:
set DateFirst 6 /* 索性把周六设为第1天 */
select DATEADD(day, 1-Datepart(weekday, DATEADD(hour,7,getdate() ) ) ,DATEADD(hour,7,getdate() ))
然而我的活动都是在周六以后统计,统计的范围是再上一个周六到,到上一个周五。并且开始的时间是00:00:00 结束的时间23:59:59.如何能从时间中获取日期,再加上指定时间呢, 问题又来了。
Datename()函数要分别取年、月、日再用。
我还想到用转换函数convert(),一种是转字符串再接上指定的时间,可以直接用来和时间字段比较。
或者将时间转化成日期,再转成时间,应该会变成00:00:00不过如果移动的话还要再转成datetime型。
最后我选择第二种,先声明一个变量 declare @bjt datetime = DATEADD(hour,7,getdate() ),用来存储北京时间,这样减少重复调用函数,同时也不会由于getdate()变化带来结果差异。
因为steemsql时间比北京时间晚7小时,所以要把时间移动到周五:
移动到周五的时间
DATEADD(day, -Datepart(weekday, @bjt) ,@bjt)
取日期
convert(varchar(10),DATEADD(day, -Datepart(weekday, @bjt) ,@bjt) ,120)
取北京时间0点,即steemsql时间17点的字符串
convert(varchar(10),DATEADD(day, -Datepart(weekday, @bjt) ,@bjt) ,120)+' 17:00:00'
将0点的时间的字符串转成datetime型
convert(datetime, convert(varchar(10),DATEADD(day, -Datepart(weekday, @bjt) ,@bjt) ,120)+' 17:00:00')
所以上个周六的0点和上上个周六的0点对应的steemsql时间分别是:
declare @end datetime =convert(datetime, convert(varchar(10),DATEADD(day, --Datepart(weekday, @bjt) ,@bjt) ,120)+' 17:00:00')
declare @start datetime =convert(datetime, convert(varchar(10),DATEADD(day, -7-Datepart(weekday, @bjt) ,@bjt) ,120)+' 17:00:00')
所以这个子句应该是:
created >=@start and created<@end
纯sql感觉有些复杂。等我学会python(或者C#)就好了吧。好吧我承认我啥也不会。
欢迎各位偶像莅临指导,不胜荣幸&感激!感谢批评和帮助!!