【问题标题】:sql working days holidayssql工作日假期
【发布时间】:2013-12-15 15:03:45
【问题描述】:

我见过这种函数在其他编码语言(Python、jQuery 等)中的不同版本,但在 SQL 中却没有。我有一个程序需要计算一个从创建日期起 65 天的日期,但它不能包括周末或节假日。我们已经有了一个功能,它只能将工作日添加到日期,但不考虑假期。我们有一个假期表,其中列出了所有的假期日期,tblHolidayDates 有一个标准日期格式的 HolidayDate 列。

我该怎么做?如果有人可以给我一个 CREATE TABLE 查询,我也会考虑也许只是创建一个日历表——它只需要日期、工作日和假期列。

下面我给出了添加工作日的当前循环函数,但它缺少节假日。任何帮助将不胜感激!

ALTER FUNCTION [dbo].[AddWorkDaysToDate]
(   
@fromDate       datetime,
@daysToAdd      int
)
RETURNS datetime
AS
BEGIN   
DECLARE @toDate datetime
DECLARE @daysAdded integer

-- add the days, ignoring weekends (i.e. add working days)
set @daysAdded = 1
set @toDate = @fromDate

while @daysAdded <= @daysToAdd
begin
-- add a day to the to date
set @toDate = DateAdd(day, 1, @toDate)
-- only move on a day if we've hit a week day
if (DatePart(dw, @toDate) != 1) and (DatePart(dw, @toDate) != 7)
begin
    set @daysAdded = @daysAdded + 1
end
end

RETURN @toDate

END

【问题讨论】:

  • 我删除了 MySQL 标记,因为该问题使用 SQL Server 语法。
  • 如果您决定创建日历表,则应删除假期表。这样,您只需维护一组数据。您不需要工作日列,因为您可以使用 datepart() 来获得它。稍后您可能会发现需要添加会计年度/期间/季度字段。

标签: sql sql-server


【解决方案1】:

几年前我写了一个 SQL 函数来构建一个动态假期表作为表函数。链接如下:

http://www.joebooth-consulting.com/sqlServer/sqlServer.html#CalendFunc

希望对你有帮助...

您可以通过如下 SQL 语句访问表函数(或您自己的假期表)来确定假期数

SELECT count(*) FROM holiday_date(2013)
WHERE holiday_date BETWEEN @fromDate AND @toDate

然后使用 dateAdd() 将计数添加到返回的日期。

如果您的假期可能在周末,请将以下内容添加到 WHERE 子句中

   AND DatePart(dw, Holiday_date) != 1) and (DatePart(dw, holiday_date) != 7)

【讨论】:

  • 这太棒了!对我正在进行的项目帮助很大,能够使用自定义假期!
  • 很高兴它帮助了迈克,总感觉更好的方式来处理假期。
【解决方案2】:

我总是使用从过去大约 5 年到未来 10 年的静态日期表来实现这一点,每个日期都标有“工作日”状态,有时还根据需要标记其他标志。以前使用 MS-SL 服务器我会通过 WHILE 循环快速实现这一点,我认为 MySQL 支持相同的语法

WHILE (condition)
BEGIN
 INSERT date
END

要创建表,请使用企业管理器 UI 或类似的东西

CREATE TABLE DateTable
 (
   actual_date datetime NOT NULL,
   is_holiday bit NOT NULL
 )

【讨论】:

  • 日期表的日期时间数据类型不合适。 OP 正在使用具有可用日期数据类型的 sql server。此外,如果您要存储假期信息,则存储假期名称比位函数有用得多。我减 1。
  • 当然很大程度上取决于使用情况,但我认为原始帖子没有标记为 MS SQL Server,当然也没有附加版本:2008 年之前没有单独的“日期”数据类型,我不确定是否所有版本的 MySQL 都支持该类型。对于大多数使用场景,存储分配的差异不会太大,但您肯定是正确的,对于 MS SQL Sever 2008 及更高版本,Date 是更好的选择。问题是关于创建一个日历表,它需要指示工作日,而不是它们有什么标签,所以我认为位标志比标签更有用?
【解决方案3】:

假设我们有一个包含 actual_date (date)is_holiday (bit) 列的 DateTable,其中包含所有日期以及所有工作日的 is_holiday=0:

SELECT actual_date from 
(
    SELECT actual_date, ROW_NUMBER() OVER(ORDER BY actual_date) AS Row 
    FROM DateTable
    WHERE is_holiday= 0 and actual_date > '2013-12-01'
) X
WHERE row = 65

这将找到 2013-12-01 加上 65 个工作日,跳过节假日。

【讨论】:

  • 好主意,但似乎不起作用(ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效,除非还指定了 TOP 或 FOR XML。)
  • @Steve - 你是对的,但 ORDER BY 仅在 OVER() 子句中是必需的(并且允许的)。删除第二个 ORDER BY 后,查询现在可以在 SQL Server 中正确执行。
猜你喜欢
  • 2012-11-08
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多