获得一周中的某一天(第二个星期二等)

时间:2014-04-02 20:03:41

标签: sql sql-server tsql

我需要一个算法来计算当月的星期几。像本月的第一个星期五,本月的第3个星期一等)。

任何想法都表示赞赏。

以下是最终结果:

declare @dt date =  GetDate()

declare @DayOfWeek tinyint = datepart(weekday,@dt)
declare @DayOfMonth smallint = day(@dt)
declare @FirstDayOfMonth date = dateadd(month,datediff(month,0,@dt),0)
declare @DayOfWeekInMonth tinyint = @DayOfMonth / 7 + 1 -
        (case when day(@FirstDayOfMonth) > day(@dt) then 1 else 0 end)
declare @Suffix varchar(2) = 
        case 
            when @DayOfWeekInMonth = 1 then 'st'
            when @DayOfWeekInMonth = 2 then 'nd'
            when @DayOfWeekInMonth = 3 then 'rd'
            when @DayOfWeekInMonth > 3 then 'th'
        end

select 
    cast(@DayOfWeekInMonth as varchar(2)) 
    + @Suffix 
    + ' ' 
    + datename(weekday,@Dt) 
    + ' of ' 
    + datename(month,@dt) 
    + ', ' 
    + datename(year,@Dt)

PS:如果你能想出一个更好的方式来陈述问题,请做。

6 个答案:

答案 0 :(得分:1)

Followint代码今天会为您提供1st Wednesday of April 2014

SELECT cast((DATEPART(d, GETDATE() - 1) / 7) + 1 as varchar(12)) 
+ 'st ' + DATENAME(WEEKDAY, getdate()) + ' of ' +
DATENAME(month, getdate()) + ' ' + DATENAME(year, getdate());

对于任何日期,请使用以下代码。它为示例中的5th Tuesday of April 2014提供了@mydate = '2014-04-29'

DECLARE @mydate DATETIME;
SET @mydate = '2014-04-29';

SELECT 
case
    when DATEPART(d, @mydate) = 1 then  cast((DATEPART(d, @mydate ) / 7) + 1 as varchar(12)) 
    else cast((DATEPART(d, @mydate - 1) / 7) + 1 as varchar(12)) 
end
+ 
case
    when  (DATEPART(d, @mydate - 1) / 7) + 1  = 1 then  'st '
    when  (DATEPART(d, @mydate - 1) / 7) + 1  = 2 then  'nd '  
    when  (DATEPART(d, @mydate - 1) / 7) + 1  = 3 then  'rd '   
    else 'th '
end
+ DATENAME(WEEKDAY, @mydate) + ' of ' +
DATENAME(month, @mydate) + ' ' + DATENAME(year, @mydate) as [Long Date Name]

答案 1 :(得分:1)

Okeeeey我的tuuuurn,

请评价我的答案隐喻嗯,这是乔德:

declare  @v_month nvarchar(2) = '04'
        ,@v_annee nvarchar(4) = '2014'

declare @v_date date = convert(date,@v_annee+'-'+@v_month+'-01')
declare @v_date_2 date = dateadd(M,1,@v_date)

if OBJECT_ID('temp') is not null
    drop table temp

create table temp(_date date, _DayOfMonth nvarchar(20), _order int)

while (@v_date<@v_date_2)
begin
    set @v_date =@v_date;
    WITH _DayOfWeek AS (
            SELECT 1 id, 'monday' Name UNION ALL
            SELECT 2 id, 'tuesday' Name UNION ALL
            SELECT 3 id, 'wednesday' Name UNION ALL
            SELECT 4 id, 'thursday' Name UNION ALL
            SELECT 5 id, 'friday' Name UNION ALL
            SELECT 6 id, 'saturday' Name UNION ALL
            SELECT 7 id, 'sunday' Name)
    insert into temp(_date,_DayOfMonth)
     SELECT
         @v_date
        ,(select Name from _DayOfWeek where id = DATEPART(WEEKDAY,@v_date))

    SET @v_date = DATEADD(DAY,1,@v_date)

END

UPDATE tmp1
    SET _order = _order_2
FROM temp tmp1
INNER JOIN
    (SELECT *, ROW_NUMBER() OVER(PARTITION BY _DayOfMonth ORDER BY _date ASC) AS     _order_2 FROM temp) tmp2
        ON tmp1._date = tmp2._date

SELECT * FROM temp

SELECT *
FROM temp
WHERE _DayOfMonth = 'thursday'
AND _order = 3

我希望这会对你有所帮助:) 祝你好运

答案 2 :(得分:0)

好的,这就是我提出的问题,我会给所有回答的人+1:

declare @dt date =  GetDate()

declare @DayOfWeek tinyint = datepart(weekday,@dt)
declare @DayOfMonth smallint = day(@dt)
declare @FirstDayOfMonth date = dateadd(month,datediff(month,0,@dt),0)
declare @DayOfWeekInMonth tinyint = 
    @DayOfMonth / 7 + 1 
    - (case when day(@FirstDayOfMonth) > day(@dt) then 1 else 0 end)
declare @Suffix varchar(2) = 
        case 
            when @DayOfWeekInMonth = 1 then 'st'
            when @DayOfWeekInMonth = 2 then 'nd'
            when @DayOfWeekInMonth = 3 then 'rd'
            when @DayOfWeekInMonth > 3 then 'th'
        end

select 
    cast(@DayOfWeekInMonth as varchar(2)) 
    + @Suffix 
    + ' ' 
    + datename(weekday,@Dt) 
    + ' of ' 
    + datename(month,@dt) 
    + ', ' 
    + datename(year,@Dt)

答案 3 :(得分:0)

declare @dt date = getdate()

declare @DayOfMonth smallint = datepart(d, @dt)

declare @Suffix varchar(2) = 
    case
        when floor((@DayOfMonth - 1) / 7.0) = 0 then 'st' -- implies there were no such days previously in the month
        when floor((@DayOfMonth - 1) / 7.0) = 1 then 'nd'
        when floor((@DayOfMonth - 1) / 7.0) = 2 then 'rd'
        else 'th'
    end 

select cast(floor((@DayOfMonth - 1) / 7.0) + 1 as varchar(1)) + @Suffix + 
' ' + datename(weekday, @dt) + ' of ' + datename(month, @dt) + 
', ' + datename(year, @dt)

答案 4 :(得分:0)

DECLARE @dt DATETIME
SET @dt = DATEADD(d, 6, GETDATE())

SELECT @dt, 
    CAST((DAY(@dt) / 7) + CASE WHEN DATEPART(weekday, @dt) >= DATEPART(weekday, CAST(MONTH(@dt) AS NVARCHAR) + '/01/' + CAST(YEAR(@dt) AS NVARCHAR)) THEN 1 ELSE 0 END AS NVARCHAR)
  + '' + CASE (DAY(@dt) / 7) + CASE WHEN DATEPART(weekday, @dt) >= DATEPART(weekday, CAST(MONTH(@dt) AS NVARCHAR) + '/01/' + CAST(YEAR(@dt) AS NVARCHAR)) THEN 1 ELSE 0 END
            WHEN 1 THEN N'st'
            WHEN 2 THEN N'nd'
            WHEN 3 THEN N'rd'
            ELSE N'th'
         END
  + ' ' + DATENAME(dw, @dt)
  + ' of ' + DATENAME(M, @dt)
  + ', ' + CAST(YEAR(@dt) AS NVARCHAR)

结果是一个SELECT(如果@dt的赋值发生在前面),但基本上与你的逻辑相同。

答案 5 :(得分:0)

以下代码将为您指定的任何月份或年份中的任何一天提供DATE。我所拥有的所有变量都是为了减少重复逻辑以提高代码速度。

此代码为您提供1st Monday in February in 2013

的日期
DECLARE @DayNumber INT = 1
    ,@DayWeekNumber INT = 2
    ,@MonthNumber INT = 2
    ,@YearNumber INT = 2013
    ,@FoM DATE
    ,@FoMWD INT;

SET @FoM    = DATEFROMPARTS(@YearNumber,@MonthNumber,1)
SET @fomwd  = DATEPART(WEEKDAY, @FoM);

SELECT CASE WHEN @fomwd = @DayWeekNumber THEN DATEADD(WEEK, @DayNumber - 1, @FoM)
            WHEN @fomwd < @DayWeekNumber THEN DATEADD(DAY, @DayWeekNumber - @fomwd, DATEADD(WEEK, @DayNumber - 1, @FoM))
            WHEN @fomwd > @DayWeekNumber THEN DATEADD(DAY, @DayWeekNumber - @fomwd, DATEADD(WEEK, @DayNumber, @FoM))
        END AS DateOfDay;