Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从SQL Server的持续时间表中获取排除已定义工作日的持续时间?_Sql_Sql Server - Fatal编程技术网

如何从SQL Server的持续时间表中获取排除已定义工作日的持续时间?

如何从SQL Server的持续时间表中获取排除已定义工作日的持续时间?,sql,sql-server,Sql,Sql Server,我试图得到两个日期之间的持续时间,每个月的周末除外。如果持续时间加上两个月,我有一个两表,一个用来计算持续时间,另一个用来计算工作日 我的目标是: 将持续时间拆分为每个月,例如: 我想星期五是周末 持续时间表: StartDate Endate Duration 2021-03-17 2021-03-25 8 2021-03-28 2021-04-02 5 预期成果:

我试图得到两个日期之间的持续时间,每个月的周末除外。如果持续时间加上两个月,我有一个两表,一个用来计算持续时间,另一个用来计算工作日

我的目标是:

将持续时间拆分为每个月,例如: 我想星期五是周末

持续时间表:

  StartDate            Endate          Duration

  2021-03-17         2021-03-25           8
  2021-03-28         2021-04-02           5
预期成果:

  StartDate            Endate          Duration

  2021-03-17         2021-03-25           8
  2021-03-28         2021-03-31           4
  2021-04-01         2021-04-02           1
计算的持续时间考虑了开始日期和结束日期,但休息日=>周五除外 获取日历日期SQL函数:

USE [Attendance]
GO
/****** Object:  UserDefinedFunction [dbo].[Get_Calendar_Date]    Script Date: 3/18/2021 12:26:36 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Get_Calendar_Date]
(
    @StartDate DATETIME
,   @EndDate DATETIME
)
RETURNS TABLE
AS
 
RETURN
(
    SELECT  Tbl_Obj.RNo
        ,   DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate) AS [Date]
        ,   DATEPART(quarter,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [Quarter]
        ,   DATEPART(dayofyear,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [DayofYear]
        ,   DATEPART(WEEK,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [WeekofYear]
        ,   DATEPART(YEAR,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [Year]
        ,   DATEPART(MONTH,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [Month]
        ,   DATEPART(DAY,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [Day]
        ,   DATEPART(weekday,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [Weekday]
        ,   DATENAME(MONTH,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [MonthName]
        ,   DATENAME(weekday,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)) AS [WeekdayName]
        ,   (RIGHT( REPLICATE('0',(4)) +
                CONVERT([VARCHAR],DATEPART(YEAR,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)),0)
                ,(4)
             )+
             RIGHT( REPLICATE('0',(2)) +
                CONVERT([VARCHAR],DATEPART(MONTH,DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate)),0)
                ,(2)
             )
            ) AS [Vintage]
 
    FROM    ( SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) AS [RNo]
              FROM sys.all_objects WITH (NOLOCK)
            ) Tbl_Obj
          
    WHERE   DATEADD(DAY,Tbl_Obj.RNo-1,@StartDate) <= @EndDate
)
       
   

如何从SQL Server工期表中获取排除已定义周末的工期?

我建议使用递归CTE扩展天数,然后进行筛选:

with cte as (
      select id, startdate, enddate
      from duration
      union all
      select id, dateadd(day, 1, startdate), enddate
      from cte
      where startdate < enddate
     )
select min(startdate), max(startdate),
       sum(case when datepart(weekday, startdate) not in (1, 7) then 1 else 0 end) as duration
from cte
group by id, year(startdate), month(startdate);
这假设每一行都有一个id,以便简化合并一行中所有结果的过程

请注意,这使用了一周中某一天的内置函数。我看不出你的表有什么用处,因为它仍然依赖于从datepart获取星期的日期


是一个数据小提琴。

听起来日历表在这里可能很有用。另外,为什么要对所有位置的sys.all_对象使用NOLOCK…?很抱歉,我的问题没有被澄清,我对这个问题感到困惑,我已经更新了我的问题。我坚持我的说法,好像日历表在这里可能有用。这并不能回答为什么要对sys.all_对象使用NOLOCK。另外,如何获得2021-04-01至2021-03-02的持续时间为1?事情怎么在开始前30天结束?对不起,这是我的错误,我已经更新了我的答案,我的意思是2021-04-01到2021-04-02你知道你需要一个日历表。通过简单的搜索,可以找到数百个示例和数千个讨论,这些示例和讨论涉及一个人的总体以及工作日和非工作日所需的逻辑。这种搜索也会遇到关于假期和其他非工作日(如灾难)的讨论。相信我-您需要这样做,或者其他人需要修复您的代码。但出于某种原因,我需要使用表days,因为它与其他表有关系。@csharp_devloper31。您可以加入到它,而不是使用大小写表达式。没有实用工具,因为SQL Server有一个功能可以做完全相同的事情。使用您提供的另一个解决方案,我想我已经修复了我的解决方案。我在另一个问题中说,我需要一个自定义休假,而不是1,7天,请再次查看我的另一个问题表,名为working_days
with cte as (
      select id, startdate, enddate
      from duration
      union all
      select id, dateadd(day, 1, startdate), enddate
      from cte
      where startdate < enddate
     )
select min(startdate), max(startdate),
       sum(case when datepart(weekday, startdate) not in (1, 7) then 1 else 0 end) as duration
from cte
group by id, year(startdate), month(startdate);