sql - 将 X 个工作日添加到日期

标签 sql sql-server sql-server-2008 tsql

我有一个使用公司日历来跟踪所有工作日的 PostingPeriod 表。简化后,它看起来像这样:

Date        Year Quarter Month Day IsWorkingDay
25.06.2015  2015 2       6     25  1
26.06.2015  2015 2       6     26  1
27.06.2015  2015 2       6     27  0

我有另一个表,其中包含所有采购行,其中包含订单日期、供应商确认的交货日期以及订单日期和交货日期之间工作日内允许的最长时间范围:

PurchID  OrderDate  ConfDelivery  DeliveryDays
1234     14.04.2015 20.05.2015    30
1235     14.04.2015 24.05.2015    20

我想创建一个新列,返回每个订单的最大允许日期(无论工作日与否)。通常的方法(工作日/5 得到周数,乘以 7 得到天数)不起作用,因为需要考虑所有假期等。 由于这是用于为 OLAP 数据库提供数据的 DWH,因此性能不是问题。

最佳答案

您可以使用 ROW_NUMBER 为每个工作日分配一个任意索引,例如

SELECT  Date, WorkingDayIndex = ROW_NUMBER() OVER(ORDER BY Date)
FROM    dbo.Calendar

这会给你类似的东西:

Date        WorkingDayIndex
-----------------------------
2015-04-27      80
2015-04-28      81
2015-04-29      82
2015-04-30      83
2015-05-01      84
2015-05-05      85
2015-05-06      86
2015-05-07      87

然后,如果您想知道距离给定日期 n 个工作日的日期,请找到索引 n 更高的日期,即 2015-04-27索引为 80,因此 5 个工作日后索引为 85,结果为 2015-05-05。

完整的工作示例

/***************************************************************************************************************************/
-- CREATE TABLES AND POPULATE WITH TEST DATA
SET DATEFIRST 1;
DECLARE @Calendar TABLE (Date DATE, IsWorkingDay BIT);
INSERT @Calendar
SELECT  TOP 365 DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY object_id), '20141231'), 1 FROM sys.all_objects;
UPDATE  @Calendar
SET     IsWorkingDay = 0
WHERE   DATEPART(WEEKDAY, Date) IN (6, 7)
OR      Date IN ('2015-01-01', '2015-04-03', '2015-04-06', '2015-05-04', '2015-05-25', '2015-08-31', '2015-12-25', '2015-12-28');
DECLARE @T TABLE (PurchID INT, OrderDate DATE, ConfDeliveryDate DATE, DeliveryDays INT);
INSERT @T VALUES (1234, '20150414', '20150520', 30), (1235, '20150414', '20150524', 20);

/***************************************************************************************************************************/
-- ACTUAL QUERY
WITH WorkingDayCalendar AS
(   SELECT  *, WorkingDayIndex = ROW_NUMBER() OVER(ORDER BY Date)
    FROM    @Calendar
    WHERE   IsWorkingDay = 1
)
SELECT  *
FROM    @T AS t
        INNER JOIN WorkingDayCalendar AS c1
            ON c1.Date = t.OrderDate
        INNER JOIN WorkingDayCalendar AS c2
            ON c2.WorkingDayIndex = c1.WorkingDayIndex + t.DeliveryDays;

如果这是一个常见的要求,那么您可以将 WorkingDayIndex 设置为日历表中的一个固定字段,这样您就不需要在每次需要时都计算它。

关于sql - 将 X 个工作日添加到日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31052183/

相关文章:

mysql在表中选择唯一用户并根据列对其进行多次计数

php - 在php中添加搜索过滤器

sql-server - 通过IP地址连接到SQL Server

sql-server-2008 - SQLBulkCopy 与目标表中的标识插入

sql - 在SQL中删除保留旧条目的重复数据

SQL - 如何跨行转换和合并数据

c# - 在命令文本中设置 ANSI_NULLS 会出现错误

sql - 创建时间数据中缺失的分钟记录以完成一天(每天 1440 条记录)

c# - 检查删除一行是否安全

SQLite 修剪字符串中的结尾字符