【问题标题】:How to count business days from a given date in SQL Server using a calendar reference table如何使用日历参考表从 SQL Server 中的给定日期计算工作日
【发布时间】:2015-07-31 22:10:09
【问题描述】:

我有两张桌子。一个表是具有date 列和kindofday 列的日历。 kindofday 列包含“bankday”、“saturday”、“sunday”和“holiday”。我需要考虑假期,否则网上有几个查询会起作用......

        date                          kindofday
1999-08-24 00:00:00:000                bankday

我正在努力构建一个可以计算从给定日期开始的工作日数的查询。比如:

Select [date] + 12 business days。我不确定如何使用日历表作为参考 - 基本上我需要在此日历表中找到一个日期,然后将该列倒计时几个工作日并提取该日期。我将把它放在一个函数中,所以不用担心复杂性。可能有一个愚蠢的简单解决方案,我只是没有看到。

我愿意接受任何考虑到假期的解决方案,即使他们不使用我的日历表。我可以更改日历表,但是我需要这样做才能完成这项工作...即:使用binary 而不是string 'bankday' 等...

我试过这个:我已经从日历中删除了所有非银行日,并添加了一个 integer 键,然后是 set @date = (select key from calendar where @date=[date],然后将工作日数量添加到该键并返回日期,但问题是当@date 是非银行日时,它不会在日历表中找到匹配项...

【问题讨论】:

  • 附注一下,您的date 列的类型似乎是datetime。将日期存储为时间戳是自找麻烦。
  • @nord,是的,我在查询中进行转换以删除时间戳
  • 它不必首先在数据库中。

标签: sql-server date count calendar


【解决方案1】:

我偶然发现了这个较老的问题,并对使用窗口函数来消除嵌套查询感到好奇

SELECT DISTINCT TOP (@count)
    @end_date = MAX(date) OVER ()
FROM
    Calendar
WHERE
    date > @start_date
    AND kindofday = 'bankday'

事实上,MAX(date) OVER() 对于您甚至不需要 DISTINCT 的每一行都是相同的。

SELECT TOP (@count)
    @end_date = MAX(date) OVER ()
FROM
    Calendar
WHERE
    date > @start_date
    AND kindofday = 'bankday'

这是一个完整的例子:

DECLARE @end_date AS DATETIME
DECLARE @start_date AS DATETIME = '12/15/2016'
DECLARE @count INT = 12

;WITH Calendar AS (
    SELECT
       CAST('12/1/2016' AS DATETIME) as date
           ,'bankday' as kindofday
    UNION ALL
    SELECT
       date + 1
       ,CASE
          WHEN date + 1 = '12/25/2016' THEN 'holiday'
          WHEN DATEPART(dw,date + 1) IN (1,7) THEN 'weekend'
          ELSE 'bankday'
       END
    FROM
       Calendar
    WHERE date + 1 <= EOMONTH(date)
)

SELECT TOP (@count)
    @end_date = MAX(date) OVER ()
FROM
    Calendar
WHERE
    date > @start_date
    AND kindofday = 'bankday'

SELECT @end_date

【讨论】:

    【解决方案2】:

    由于您使用的是 SQL Server,因此您可以使用 ranking 函数对非银行工作日进行排序并获取序列号,然后将其与您希望添加的天数相匹配。

    SELECT date
    FROM (
      SELECT date AS DATE, 
       ROW_NUMBER() OVER (ORDER BY date) AS PLUS_DAYS
      FROM calendar
      WHERE date > @start_date AND KINDOFDAY <> 'bankday'
      ORDER BY date
    ) TEMP 
    WHERE TEMP.PLUS_DAYS = @plus_days
    

    【讨论】:

    • 它应该是 KINDOFDAY = 'bankday' 但如果日历表中的 @plus_days 少于 @plus_days,它也会崩溃。例如。您正在寻找 + 12 天,但数据集中仅存在 + 10 天。
    【解决方案3】:

    将问题改写为“在@start_date 之后的下一个@count bankdays,哪一个发生在最后?”

    SELECT @end_date = MAX(date)
    FROM (
      SELECT TOP(@count)
        date
      FROM Calendar
      WHERE date > @start_date
        AND kindofday = 'bankday'
      ORDER BY date
    ) t
    

    【讨论】:

    • 非常漂亮的兄弟!我看到你在那里做了什么......我可以说非常漂亮!它就像一个魅力......把它放在函数形式中并顺利运行!感谢使用 TOP 功能...这就是我的小脑袋需要帮助的地方:)
    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多