【问题标题】:Creating a date from Week of month and Day of week in SQL server在 SQL Server 中根据月份和星期几创建日期
【发布时间】:2015-11-26 00:36:02
【问题描述】:

我必须从用户输入的 一周中(该月的周数 - 第 1、2、3、4 日和最后一个)和 星期几(星期日,星期一..)在 SQL 服务器中。

示例: 每月第四个星期日、每月最后一个星期五、第一个星期一等

我可以在 .net 中轻松做到这一点,但 SQL Server 的日期功能似乎确实有限。

我不得不使用大量逻辑来获取日期。要使用上述两个参数计算日期,我必须使用很多 datepart 函数。

关于如何为此类函数提出最佳 SQL 查询的任何建议?

【问题讨论】:

  • 如果您使用的是 sql server 2012 及更高版本,请查看DATEFROMPARTS() 函数。 msdn.microsoft.com/en-IN/library/hh213228.aspx
  • 您是否考虑过使用已有的 .NET 代码创建 CLR Stored Procedure
  • @DhruvJoshi - 是的,我确实读过它,但它需要年、月和日期作为参数。我需要的是类似于 DateFromParts 的东西,但更多的是它的深入版本。

标签: sql-server tsql date


【解决方案1】:

前几天我为另一个 OP GET Month, Quarter based on Work Week number 创建了一个函数

此函数默认采用当前年份,也可以进一步修改为采用年份作为参数。

对该功能的扩展可以产生您正在寻找的结果......

WITH X AS
(
SELECT TOP (CASE WHEN YEAR(GETDATE()) % 4 = 0 THEN 366 ELSE 365 END)-- to handle leap year 
      DATEADD(DAY 
             ,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1
             , CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '0101' )      
                      DayNumber
  From master..spt_values
 ),DatesData AS(
SELECT DayNumber [Date]
      ,DATEPART(WEEKDAY,DayNumber) DayOfTheWeek
      ,DATEDIFF(WEEK, 
            DATEADD(WEEK, 
               DATEDIFF(WEEK, 0, DATEADD(MONTH, 
                           DATEDIFF(MONTH, 0, DayNumber), 0)), 0)
              , DayNumber- 1) + 1 WeekOfTheMonth
FROM X )
SELECT * FROM DatesData
WHERE DayOfTheWeek   = 6  -- A function would expect these two parameters
 AND  WeekOfTheMonth = 4  -- @DayOfTheWeek and @WeekOfTheMonth 

【讨论】:

    【解决方案2】:

    这是一个通用公式:

    declare @month as datetime --set to the first day of the month you wish to use
    declare @week as int  --1st, 2nd, 3rd...
    declare @day as int   --Day of the week (1=sunday, 2=monday...)
    
    --Second monday in August 2015
    set @month = '8/1/2015'
    set @week = 2
    set @day = 2
    
    select dateadd(
        day,
        ((7+@day) - datepart(weekday, @month)) % 7 + 7 * (@week-1),
        @month
        )
    

    您还可以使用此反向公式找到最后一个、倒数第二个...等:

    --Second to last monday in August 2015
    set @month = '8/1/2015'
    set @week = 2
    set @day = 2
    
    select
        dateadd(
        day,
        -((7+datepart(weekday, dateadd(month,1,@month)-1)-@day)) % 7 - 7 * (@week-1),
        dateadd(month,1,@month)-1
        )
    

    【讨论】:

    • 我自己试过了,效果很好(两种情况)。这是一个易于理解且可重用的解决方案。美国的节假日大多是按月的周数计算的,所以这个功能来得很方便。
    猜你喜欢
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多