选择在特定时段发生的持续时间的一部分

时间:2016-10-20 10:41:57

标签: sql-server sql-server-2008 tsql sql-server-2008-r2

在SQL Server中,我有一个包含开始时间和结束时间的进程表,我可以使用DATEDIFF计算持续时间。

Name        StartTime           EndTime
------------------------------------------------
process1    2016-10-10 11:10    2016-10-10 11:20
process2    2016-10-10 11:40    2016-10-10 12:30

如何选择在一天(11和12)的特定时段内以秒为单位的过程持续时间的时间跨度?

因此,process1将是每小时10分钟11。 process2将是小时20分钟,小时12小时30分钟。

5 个答案:

答案 0 :(得分:0)

我是新来的。我认为这样做的伎俩,但它非常丑陋。也许有人可以更优雅地做到这一点?

SELECT 
   case 
     when HOUR(starttime) < 11 AND HOUR(endtime) = 11  then minute(endtime)
     when HOUR(starttime) < 11 AND HOUR(endtime) > 11  then 60
     when HOUR(starttime) = 11 AND HOUR(endtime) = 11  then minute(endtime) - minute(starttime)
     when HOUR(starttime) = 11 AND HOUR(endtime) > 11  then 60 - minute(starttime)
     else 0
   end AS ProcessTimeHour_11,
    case 
     when HOUR(starttime) < 12 AND HOUR(endtime) = 12  then minute(endtime)
     when HOUR(starttime) < 12 AND HOUR(endtime) > 12  then 60
     when HOUR(starttime) = 12 AND HOUR(endtime) = 12  then minute(endtime) - minute(starttime)
     when HOUR(starttime) = 12 AND HOUR(endtime) > 12  then 60 - minute(starttime)
     else 0
   end AS ProcessTimeHour_12
from StuffAndThings

答案 1 :(得分:0)

  SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,'2016-10-10 11:10','2016-10-10 12:20'),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference

使用timeDifference -

SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,StartTime,EndTime),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference 
from #YourTableName

使用Days和TimeDiffernece

    declare @start_time as varchar(150);
    declare @end_time as varchar(150);
    set @start_time='2016-10-10 10:10';
    set @end_time='2016-10-12 12:10'

    SELECT datediff(day,@start_time,@end_time) as dayDifference,
CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,@start_time,@end_time),'2011-01-01 00:00:00') AS TIME(0))
 as timeDifference

答案 2 :(得分:0)

要处理一般情况,您可以尝试类似

的内容
    --drop table #processes 
CREATE TABLE #processes 
    (
    name  varchar(50),
    StartTime  Datetime,
    EndTime  DateTime
    );

    insert #processes VALUES('proc1','20161010 11:10','20161010 11:20');
    insert #processes VALUES('proc2','20161010 11:40','20161010 12:20');
    insert #processes VALUES('proc3','20161010 10:40','20161010 12:20');

;WITH HRS   AS  (SELECT 0 HR 
                UNION ALL
                SELECT HR + 1 FROM HRS WHERE HR < 23),
    MINS    AS  (SELECT 0 MN 
                UNION ALL
                SELECT MN + 1 FROM MINS WHERE MN < 59),
    TIMES   AS  (SELECT HR,MN FROM HRS CROSS JOIN MINS)
    SELECT name,starttime,endtime,Count(0) AS mins FROM #processes
                    JOIN TIMES 
                            ON (HR > datepart(hh,Starttime) 
                                OR HR = datepart(hh,Starttime)   AND MN >= datepart(n,STARTtIME))
                                AND 
                                (HR < datepart(hh, EndTime) 
                                OR HR = datepart(hh, EndTime)  AND MN < datepart(n,EndTime))

                    WHERE HR = 11 --hour is 11

        GROUP BY name,
                    starttime,
                    endtime                     



    drop table #processes;          

答案 3 :(得分:0)

create table #temp (Name varchar(5), starttime datetime, EndTime datetime)

insert into #temp values(1,'2016-10-10 11:10','2016-10-10 11:20' )
insert into #temp values(2,'2016-10-10 11:40','2016-10-10 12:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 11:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 12:30' )  


    DECLARE @firstTime time ,@secondTime time
    set @firstTime ='11:00'
    set @secondTime ='12:00'

    select
     CASE WHEN CONVERT(time(0), starttime) < @firstTime AND CONVERT(time(0), EndTime) > @secondTime  THEN  DATEDIFF(ss,@firstTime,@secondTime)
          WHEN CONVERT(time(0), EndTime) > @secondTime THEN DATEDIFF(ss,CONVERT(time(0), starttime),@secondTime)
          WHEN CONVERT(time(0), starttime) < @firstTime THEN DATEDIFF(ss,CONVERT(time(0), EndTime),@secondTime)
         ELSE DATEDIFF(ss,starttime,EndTime) 
     END
    from #temp

答案 4 :(得分:0)

这是一个为每个源记录生成每小时记录的示例。它使用递归CTE从每个记录的StartTime移动到EndTime。可能需要稍微修改才能使其适用于您的情况,但希望您能够了解此方法的工作原理。

请注意,如下面的示例所示,即使时间跨度超过日期边界,这也能正常工作。

--==================================================================================
-- Do some quick setup to get a temporary table populated with data to use:
--==================================================================================
IF OBJECT_ID('tempdb..#ProcessHistory', 'U') IS NOT NULL DROP TABLE #ProcessHistory;
CREATE TABLE #ProcessHistory (
    Name VARCHAR(20),
    StartTime DATETIME,
    EndTime DATETIME
)

INSERT INTO #ProcessHistory
VALUES  ('process1', '2016-10-10 11:10', '2016-10-10 11:20'),
        ('process2', '2016-10-10 11:40', '2016-10-10 12:30'),
        ('process3', '2016-10-10 22:21', '2016-10-11 02:36');

--==================================================================================
-- Use a recursive CTE to generate hourly data for each record:
--==================================================================================
WITH HourlyData AS (
    -- Anchor:
    SELECT
        ph.Name [ProcessName],
        ph.StartTime [StartTime],
        ph.EndTime [EndTime],
        -- Get the current hour with date:
        DATEADD(MINUTE, -DATEPART(MINUTE, ph.StartTime), ph.StartTime) [CurrentHour],
        -- Calculate the next hour for use later:
        DATEADD(MINUTE, 60 - DATEPART(MINUTE, ph.StartTime), ph.StartTime) [NextHour],
        -- Determine how many minutes the process was active this hour:
        CASE
            WHEN DATEDIFF(MINUTE, ph.StartTime, ph.EndTime) > 60 - DATEPART(MINUTE, ph.StartTime)
                THEN 60 - DATEPART(MINUTE, ph.StartTime)
            ELSE DATEDIFF(MINUTE, ph.StartTime, ph.EndTime)
        END [Minutes]
    FROM #ProcessHistory ph

    UNION ALL

    -- Recurse:
    SELECT
        hd.ProcessName,
        hd.StartTime,
        hd.EndTime,
        hd.NextHour [CurrentHour],
        DATEADD(HOUR, 1, hd.NextHour) [NextHour],
        -- Determine how many minutes the process was active this hour:
        CASE
            WHEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime) < 60
                THEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime)
            ELSE 60
        END
    FROM HourlyData hd
    WHERE hd.NextHour < hd.EndTime
)
SELECT
    hd.ProcessName,
    hd.CurrentHour [HourWithDate],
    CONVERT(DATE, hd.CurrentHour) [Date],
    DATEPART(HOUR, hd.CurrentHour) [Hour],
    hd.Minutes
FROM HourlyData hd
ORDER BY
    hd.ProcessName,
    hd.CurrentHour;

以上示例的输出如下所示:

ProcessName HourWithDate            Date        Hour    Minutes
process1    2016-10-10 11:00:00.000 2016-10-10  11      10
process2    2016-10-10 11:00:00.000 2016-10-10  11      20
process2    2016-10-10 12:00:00.000 2016-10-10  12      30
process3    2016-10-10 22:00:00.000 2016-10-10  22      39
process3    2016-10-10 23:00:00.000 2016-10-10  23      60
process3    2016-10-11 00:00:00.000 2016-10-11  0       60
process3    2016-10-11 01:00:00.000 2016-10-11  1       60
process3    2016-10-11 02:00:00.000 2016-10-11  2       36
相关问题