在steemsql(mssql)下如何获得上一个周六的指定时间How to get the certain time of last Saturday in Steemsql(mssql)

in #mssql7 years ago (edited)

最近我每周都要去统计“华语好声音”和“三个一”活动的一周文章列表。所以在条件语句中,总是少不了限制时间。例如,上周统计“华语好声音”的一个条件子句就是

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#)就好了吧。好吧我承认我啥也不会。

欢迎各位偶像莅临指导,不胜荣幸&感激!感谢批评和帮助!!

Sort:  

功夫不负有心人,就这样被你试出来了。

哈哈还是你懂我哈哈
其实我还试了很多相关、但是实现这个功能没有用的东西。
但只有这样才能边干边学习呀!

向你学习,边干边学,最有效率。

@tvb 一姐果然不是盖的,我看了以上的steemsql,真是"雾里看花" 有看没懂的感觉 (甚至开始有些晕头转向@_@)

你想懂就能懂啦

@tvb, 干的漂亮!

情人节貌似快到了,@cn-cutie.pie 可可 我们去哪里浪漫一下?

好瘋狂啊...... 怎麽這裏好像每一個人都懂寫code 但我偏偏以前沒有學好........

我也不怎么会呀

steemsql比steemjs好用多了,(´;︵;`)

steemjs坑好多,不好用。

我还想研究研究steem.js呢。再说坑多你正好提bug

@tvb, 我好欣赏你滴~~~ img

你男朋友呢

辛苦你了,一姐!
早点休息,身体重要!

你也是呀,赶紧睡呀,大半夜就咱俩不睡哈哈这可不好哈哈

哇塞,好高深好崇拜@tvb!编程能力这么强。我都看痴了

你真是什么都懂一点啊……研究的东西越来越深奥了……

其实很简单的,内行人一看就会笑话我的

@tvb姐,不久前发现有这个SQL tutorial :
https://www.w3schools.com/sql/default.asp
datepart的部分:
https://www.w3schools.com/sql/func_sqlserver_datepart.asp
interval
Required. The time/date part to return. Can be one of the following
values:
year, yyyy, yy = Year
quarter, qq, q = Quarter
month, mm, m = month
dayofyear = Day of the year
day, dy, y = Day
week, ww, wk = Week
weekday, dw, w = Weekday
hour, hh = hour
minute, mi, n = Minute
second, ss, s = Second
millisecond, ms = Millisecond

有一些SQL Server Date Functions可以用
https://www.w3schools.com/sql/sql_ref_sqlserver.asp

我用的就是这个函数,但不是你想的那么简单的直接就能得到星期几的。

何况我不只是想要知道现在星期几,你能不能仔细看看人家文章。。。。

我看了,后面那个部分是神来之笔,很厉害! 👍
只是刚好看到有tutorial, 可以方便TVB姐不用测试function的参数是什么。
还有一些其他Date Functions可以玩玩。😊

测试的过程也是一种收获,不然我记不住。而且@@@datefirst的问题我总是要试试才能弄明白的。Datepart函数在星期这个问题上不能直接用

Coin Marketplace

STEEM 0.17
TRX 0.13
JST 0.027
BTC 59727.23
ETH 2674.33
USDT 1.00
SBD 2.44