Sql server 如何计算两个日期(周末和节假日除外)之间的分钟数?

Sql server 如何计算两个日期(周末和节假日除外)之间的分钟数?,sql-server,Sql Server,如何计算SQL Server 2008R2表中两个日期(从第一行到最后)之间的分钟数(分钟计算为周一上午7点到周五晚上7点) 我试过类似的方法,但不起作用 DECLARE @StartDate DateTime='2015-06-12 13:03:00' DECLARE @EndDate DateTime='2015-06-16 10:08:00' IF DATEPART(WEEKDAY,@StartDate) = 1 SET @S

如何计算SQL Server 2008R2表中两个日期(从第一行到最后)之间的分钟数(分钟计算为周一上午7点到周五晚上7点)

我试过类似的方法,但不起作用

     DECLARE  @StartDate DateTime='2015-06-12 13:03:00'
     DECLARE @EndDate DateTime='2015-06-16 10:08:00'

        IF DATEPART(WEEKDAY,@StartDate) = 1
            SET @StartDate = DATEADD(HOUR,8,DATEADD(DAY,DATEDIFF(DAY,0,@StartDate),1))
        IF DATEPART(WEEKDAY,@StartDate) = 7
            set @StartDate = DATEADD(HOUR,8,DATEADD(DAY,DATEDIFF(DAY,0,@StartDate),2))


        IF DATEPART(WEEKDAY,@EndDate) = 1
            SET @EndDate = DATEADD(HOUR,19,DATEADD(DAY,DATEDIFF(DAY,0,@EndDate),-2))
        IF DATEPART(WEEKDAY,@EndDate) = 7
            SET @EndDate = DATEADD(HOUR,19,DATEADD(DAY,DATEDIFF(DAY,0,@EndDate),-1))

        IF DATEPART(WEEKDAY,@StartDate) = 2 AND DATEPART(HH, @StartDate)<8
            SET @StartDate = DATEADD(HOUR, 8, DATEDIFF(DAY, 0, @StartDate))
        IF DATEPART(WEEKDAY,@EndDate) = 6 AND DATEPART(HH, @EndDate)>8
            SET @EndDate = DATEADD(HOUR, 19, DATEDIFF(DAY, 0, @EndDate)) 

    Declare @WorkMin int  
    Set @WorkMin=DATEDIFF(MI,@StartDate,@EndDate)-(DATEDIFF(WEEK,@StartDate,@EndDate)*2880)

    Print @WorkMin ----Out put is 2705

    ---------Actual Minutes is 1985
DECLARE@StartDate DateTime='2015-06-12 13:03:00'
声明@EndDate DateTime='2015-06-16 10:08:00'
如果DATEPART(工作日,@StartDate)=1
设置@StartDate=DATEADD(小时,8,DATEADD(天,DATEDIFF(天,0,@StartDate),1))
如果DATEPART(工作日,@StartDate)=7
设置@StartDate=DATEADD(小时,8,DATEADD(天,DATEDIFF(天,0,@StartDate),2))
如果DATEPART(工作日,@EndDate)=1
设置@EndDate=DATEADD(小时,19,DATEADD(天,DATEDIFF(天,0,@EndDate),-2))
如果DATEPART(工作日,@EndDate)=7
设置@EndDate=DATEADD(小时,19,DATEADD(天,DATEDIFF(天,0,@EndDate),-1))
如果DATEPART(工作日,@StartDate)=2,DATEPART(HH,@StartDate)8
设置@EndDate=DATEADD(小时,19,日期差(天,0,@EndDate))
声明@WorkMin int
设置@WorkMin=DATEDIFF(MI,@StartDate,@EndDate)-(DATEDIFF(WEEK,@StartDate,@EndDate)*2880)
打印@WorkMin----输出为2705
---------实际会议记录是1985年

上面的代码计算的是星期五晚上7点之后和星期一早上7点之前的分钟数。但我想排除这些分钟数。有人能帮我吗?

我有1985分钟。老实说,这是我第一次按照你的规则写剧本时得到的,我觉得这很神奇

--Working week is 7AM Monday to 7PM Friday
--Get the start date
DECLARE @StartDate DATETIME = '20150612 13:03:00';

--If the start date is in the weekend period then move it forward to 7AM Monday
DECLARE @days INT = NULL;
IF DATEPART(WEEKDAY, @StartDate) = 7 --Saturday
    SELECT @days = 2;
IF DATEPART(WEEKDAY, @StartDate) = 1 --Sunday
    SELECT @days = 1;
IF DATEPART(WEEKDAY, @StartDate) = 6 AND DATEPART(HOUR, @StartDate) > 19 --Friday after 7PM
    SELECT @days = 3;
IF DATEPART(WEEKDAY, @StartDate) = 2 AND DATEPART(HOUR, @StartDate) < 7 --Monday before 7AM
    SELECT @days = 0;
IF @days IS NOT NULL
    SELECT @StartDate = CONVERT(DATETIME, DATEPART(YEAR, DATEADD(DAY, @days, @StartDate)) + DATEPART(MONTH, DATEADD(DAY, @days, @StartDate)) + DATEPART(DAY, DATEADD(DAY, @days, @StartDate)) + ' 07:00');

--Get the end date
DECLARE @EndDate DATETIME = '20150616 10:08:00';

--If the end date is in the weekend period then move it back to 7PM Friday
SELECT @days = NULL;
IF DATEPART(WEEKDAY, @EndDate) = 7 --Saturday
    SELECT @days = -1;
IF DATEPART(WEEKDAY, @EndDate) = 1 --Sunday
    SELECT @days = -2;
IF DATEPART(WEEKDAY, @EndDate) = 6 AND DATEPART(HOUR, @EndDate) > 19 --Friday after 7PM
    SELECT @days = 0;
IF DATEPART(WEEKDAY, @EndDate) = 2 AND DATEPART(HOUR, @EndDate) < 7 --Monday before 7AM
    SELECT @days = -3;
IF @days IS NOT NULL
    SELECT @EndDate = CONVERT(DATETIME, DATEPART(YEAR, DATEADD(DAY, @days, @EndDate)) + DATEPART(MONTH, DATEADD(DAY, @days, @EndDate)) + DATEPART(DAY, DATEADD(DAY, @days, @EndDate)) + ' 19:00');

--Now calculate the raw minutes
DECLARE @Minutes INT;
SELECT @Minutes = DATEDIFF(MINUTE, @StartDate, @EndDate);

--Work out how many complete weeks we have, then take this off the result
DECLARE @CompleteWeeks INT = 0;
SELECT @CompleteWeeks = DATEDIFF(WEEK, @StartDate, @EndDate);
SELECT @Minutes = @Minutes - @CompleteWeeks * DATEDIFF(MINUTE, '20170421 19:00', '20170424 07:00'); --3600 minutes, we could just hardcode this

--Output
SELECT 'Start Date' AS metric, CONVERT(VARCHAR(50), @StartDate) AS [value]
UNION ALL
SELECT 'End Date', CONVERT(VARCHAR(50), @EndDate)
UNION ALL
SELECT 'Minutes', CONVERT(VARCHAR(50), @Minutes);
——工作周为周一上午7点至周五下午7点
--获取开始日期
声明@StartDate DATETIME='20150612 13:03:00';
--如果开始日期在周末,则将其提前到周一上午7点
声明@days INT=NULL;
如果DATEPART(工作日,@StartDate)=7--Saturday
选择@days=2;
如果DATEPART(工作日,@StartDate)=1--Sunday
选择@days=1;
如果DATEPART(工作日,@StartDate)=6,DATEPART(小时,@StartDate)>19——周五晚上7点后
选择@days=3;
如果DATEPART(工作日,@StartDate)=2,DATEPART(小时,@StartDate)<7——周一上午7点之前
选择@days=0;
如果@days不为空
选择@StartDate=CONVERT(DATETIME,DATEPART(YEAR,DATEADD(DAY,@days,@StartDate))+DATEPART(MONTH,DATEADD(DAY,@days,@StartDate))+DATEPART(DAY,DATEADD(DAY,@days,@StartDate))+07:00);
--获取结束日期
声明@EndDate DATETIME='20150616 10:08:00';
--如果结束日期在周末,则将其移回周五晚上7点
选择@days=NULL;
如果DATEPART(工作日,@EndDate)=7--Saturday
选择@days=-1;
如果DATEPART(工作日,@EndDate)=1--Sunday
选择@days=-2;
如果DATEPART(工作日,@EndDate)=6,DATEPART(小时,@EndDate)>19——周五晚上7点后
选择@days=0;
如果DATEPART(工作日,@EndDate)=2,DATEPART(小时,@EndDate)<7——周一上午7点之前
选择@days=-3;
如果@days不为空
选择@EndDate=CONVERT(DATETIME,DATEPART(YEAR,DATEADD(DAY,@days,@EndDate))+DATEPART(MONTH,DATEADD(DAY,@days,@EndDate))+DATEPART(DAY,DATEADD(DAY,@days,@EndDate))+'19:00';
--现在计算原始分钟数
声明@Minutes INT;
选择@Minutes=DATEDIFF(分钟、@StartDate、@EndDate);
--计算出我们有多少个完整的星期,然后把这个从结果中去掉
声明@CompleteWeeks INT=0;
选择@CompleteWeeks=DATEDIFF(周、@StartDate、@EndDate);
选择@Minutes=@Minutes-@CompleteWeeks*DATEDIFF(分钟,'20170421 19:00','20170424 07:00')--3600分钟,我们可以硬编码
--输出
选择“开始日期”作为度量,将(VARCHAR(50),@StartDate)转换为[值]
联合所有
选择“结束日期”,转换(VARCHAR(50),@EndDate)
联合所有
选择“分钟”,转换(VARCHAR(50),@Minutes);
也许有更好的方法可以做到这一点,但我基本上将问题分解为以下步骤:

  • 如果开始日期在“周末时段”,则将其提前至周一上午7点
  • 如果结束日期在“周末时段”,则将其向后移动到周五晚上7点
  • 计算调整日期之间的分钟数
  • 删除日期范围内每一完整周的“周末时段”分钟数(即从周五晚上7点到周一上午7点的分钟数)。由于我之前的调整,这应该是可行的
我不确定开始/结束位是否100%有效,因为您的示例日期不是很好的示例(它们都不在周末)


我试图遵循与您的脚本类似的模式(顺便说一句,基本上不起作用)。

有些地方不匹配。根据我的计算,该值为1265分钟:

下面是要生成的代码(没有求和)。它基于日历表的一个非常特定的版本——这是一种你应该学习如何将其融入你的技能集中的技术。它是静态定义的,包含的信息刚好足以说明这个特定问题;我将把它留给您,让您以更通用的方式进行调整

set nocount on;
declare @cal table (dt_start datetime not null, dt_end datetime not null); 
insert @cal(dt_start, dt_end) values 
('20150611 07:00', '20150611 19:00'), 
('20150612 07:00', '20150612 19:00'), -- friday
('20150615 07:00', '20150615 19:00'), 
('20150616 07:00', '20150616 19:00'), 
('20150617 07:00', '20150617 19:00'),
('20150618 07:00', '20150618 19:00');
select * from @cal order by dt_start;

declare @ps datetime, @pe datetime; 
set @ps = '20150612 13:03';
set @pe = '20150616 10:08';
select @ps as ps, @pe as pe; 

select --@ps as [start], @pe as [end], 
t.*, 
case when t.dt_start < @ps then @ps else t.dt_start end as s1, 
case when t.dt_end > @pe then @pe else t.dt_end end as e1,
datediff(minute, 
case when t.dt_start < @ps then @ps else t.dt_start end,   
case when t.dt_end > @pe then @pe else t.dt_end end ) as calc
from @cal as t
where t.dt_start <= @pe and t.dt_end >= @ps
order by t.dt_start
;
设置不计数;
声明@cal表格(dt_开始日期时间不为空,dt_结束日期时间不为空);
插入@cal(dt_开始,dt_结束)值
('20150611 07:00', '20150611 19:00'), 
('20150612 07:00'、'20150612 19:00'),-周五
('20150615 07:00', '20150615 19:00'), 
('20150616 07:00', '20150616 19:00'), 
('20150617 07:00', '20150617 19:00'),
('20150618 07:00', '20150618 19:00');
按dt_start从@cal order中选择*;
声明@ps datetime、@pe datetime;
set@ps='20150612 13:03';
set@pe='20150616 10:08';
选择@ps作为ps,@pe作为pe;
选择--@ps作为[开始],@pe作为[结束],
t、 *,
当t.dt_开始时<@ps,然后@ps,否则t.dt_开始结束时为s1,
当t.dt_end>@pe然后@pe else t.dtu end作为e1时的情况,
日期差(分钟),
当t.dt_开始<@ps然后@ps否则t.dt_开始结束时,
当t.dt_end>@pe然后@pe else t.dtu end)作为计算时的情况
从@cal as t
其中t.dt_start=@ps
按t.dt_开始订购
;
你第一次说你的工作时间是早上7点到晚上7点,但是你