有没有办法使用 T-SQL 语法找出每月第二个星期二的日期?
例如,3 月是 12 日,4 月是 9 日。
在不知道实际所需的输入和输出是什么的情况下,我现在只能给您一个用于将日期标识为该月的第二个星期二的谓词:
DATEPART(day,@Date) between 8 and 14 and --Find the second one in the month
DATEPART(weekday,@Date) = DATEPART(weekday,'20130319') --Make sure its a Tuesday
(我使用固定的,已知的星期二,以避免DATEFIRST
在查询运行时必须知道哪些设置有效)
这会找到当月的适当星期二,但显然@Date
可以设置为任何感兴趣的日期:
declare @Date datetime
set @Date = CURRENT_TIMESTAMP
;with Numbers as (select n from (values (0),(1),(2),(3),(4),(5),(6)) t(n)),
PotentialDates as (select DATEADD(day,n,DATEADD(month,DATEDIFF(month,'20010101',@Date),'20010108')) as Date
from Numbers
)
select * from PotentialDates where DATEPART(weekday,Date) = DATEPART(weekday,'20130319')
(而且,希望也很明显,查询可以是更大查询的一部分,@Date
而不是列值,因此这可以构成整个工作的基于集合的方法的一部分)
这就是您如何找到 2013 年所有“第二个星期二”的方法。
select
dateadd(day, 8, datediff(day, 1, dateadd(month, n, '2013-01-07')) / 7 * 7) date
from
(values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11)) t(n)
此代码将在每月的第 1 和第 3 个星期日为您提供。
declare @dt datetime
select @dt = '12/01/2014'
select dateadd(mm,datediff(mm,'',@dt),'') - datepart(dw,dateadd(mm,datediff(mm,'',@dt),'')+0)+ 8
select dateadd(mm,datediff(mm,'',@dt),'') - datepart(dw,dateadd(mm,datediff(mm,'',@dt),'')+0)+ 22
从星期日开始的几个月内,以前的答案都不起作用(它指向第二个星期日)。
SELECT @dt AS input_date,
DATEADD(mm, DATEDIFF(mm, 0, @dt), 0) --truncate date to month start
-- DATEPART(@month_start) returns month start's weekday, with Sunday starting 1;
-- Since Sunday starts at 1, we need to perform proper adjustment - move date 6 days forward (7 week days - 1 for sunday) forward and find its datepart, which will be 7
-- Result: month starting sunday, datepart returns 7; month starting Mon we return 1 (datepart of Mon + 6 days = Sunday, which is 1), month starting tue, we return 2
-- Effectivelly, datepart offset will always point last Sunday of previous month
- DATEPART(dw,
6
+ DATEADD(mm,datediff(mm,0,@dt),0) --truncate date to month start
)
-- Since we found last Sunday of previous month, we need to add 7
+ 7 AS CORRECT,
dateadd(mm,datediff(mm,'',@dt),'') - datepart(dw,dateadd(mm,datediff(mm,'',@dt),'')+0)+ 8 AS sometimes_correct
显示相对于 Pravin Pandit 答案的正确答案的图像:
我们可以扩展查找本月第一个星期二的基本原理,并创建一个执行此操作的函数,因此对于任何输入日期,它都会找到该月的第一个星期二:
ALTER FUNCTION dbo.f_time_floor_1st_tue(@date DATETIME2(3))
RETURNS DATETIME
AS
BEGIN
RETURN
DATEADD(mm, DATEDIFF(mm, 0, @date), 0) --truncate date to month start
-- DATEPART(@month_start) returns month start's weekday, with Sunday starting 1;
-- Since Sunday starts at 1, we need to perform proper adjustment - move date 6 days forward (7 week days - 1 for sunday) forward and find its datepart, which will be 7
-- Result: month starting sunday, datepart returns 7; month starting Mon we return 1 (datepart of Mon + 6 days = Sunday, which is 1), month starting tue, we return 2
-- Effectivelly, datepart offset will always point last Sunday of previous month
-- Extending this logic for finding first Tuesday, Tuesday should always return 7 we need to move Tue datepart (3) by 4 ( which is 7 days in the week minus 3
- DATEPART(dw,
4 -- 4 is adjustment so that DATEPART returns 7 for all months starting Tue
+ DATEADD(mm,datediff(mm,0,@date),0) --truncate date to month start
)
-- Since we found last weekday of previous month, we need to add 7
+ 7
;
END;
GO