I have 3 Columns in db Time Parameter(00:15) , StartTime(09:00) , EndTime (15:00)
Now I want to show all time with gap of 00:15 min between 09:00 and 15:00
What query should I write so that it returns values something like this:
09:00 - 09:15
09:15 - 09:30
09:30 - 09:45
-
-
-
-
14:45 - 15:00
Using CTE and assuming hour part of #time is zero:
declare #time time(0) = '00:15',
#start time(0) = '12:00',
#end time(0) = '15:00'
;with cte as (
select #start sTime, dateadd(minute, datepart(minute,#time), #start) eTime
union all
select eTime, dateadd(minute, datepart(minute,#time), eTime)
from cte
where dateadd(minute, datepart(minute,#time), eTime) <= #end
)
select left(sTime,5) + ' - ' + left(eTime, 5) results
from cte
--results
12:00 - 12:15
12:15 - 12:30
12:30 - 12:45
12:45 - 13:00
13:00 - 13:15
13:15 - 13:30
13:30 - 13:45
13:45 - 14:00
14:00 - 14:15
14:15 - 14:30
14:30 - 14:45
14:45 - 15:00
Use a Common table expression (CTE) to generate a table with all the times in it that you want.
Declare #strtDt smallDatetime = '15 May 2013 09:00';
Declare #endDt smallDateTime = '15 May 2013 15:00';
With DateTimes(dt) As
(Select #strtDt
Union All
Select DateAdd(minute, 15, dt)
From DateTimes
Where dt < #endDt)
Select dt from DateTimes
option (maxrecursion 10000)
Related
I am working on a SQL query where I have to select only one value of given time interval in seconds.
Suppose I give time interval=5, then the value should come after every 5 seconds. If I give time interval=60, then the value should come after every 60 seconds i.e. after every minute. If I give time interval=300, then the value should come after every 300 seconds i.e. after every 5 minutes and so on.
For this I used the following query
DECLARE #FROMDATETIME DATE = '2016-09-21 14:00',
#TODATETIME DATE = '2020-09-21 14:00',
#INTERVAL NVARCHAR(50) = '300'
DECLARE #intv INT = ((CONVERT(INT, #INTERVAL)) / 60)
SELECT
CONVERT(NVARCHAR(20), DATEANDTIME, 113) DATETIME,
ALARM, F870 'COLD JUICE PRE [PSI]',
F872 'COLD WATER PRE [PSI]', F82 'FILLER TEMP [DEGC]',
F810 'FLOW [LTR/MIN]', F869 'HOT JUICE PRE[PSI]',
F874 'HOT WATER PRE[PSI]', F867 'HOT WATER TEMP[DEGC]',
F84 'JUICE TEMP AFTER HOLD TUBE[DEGC]', F822 'PD FOR COLD PHE[PSI]',
F821 'PD FOR HOT PHE[PSI]', F8X 'PHE INLET TEMP[DEGC]',
B1 'MACHINE 1 STATUS', B2 'MACHINE 2 STATUS'
FROM
(SELECT
DATEANDTIME,
NULL ALARM, F870 F870, F872 F872, F82 F82, F810 F810, F869 F869,
F874 F874, F867 F867, F84 F84, F822 F822, F821 F821, F8X F8X,
CASE
WHEN B1 = 1 THEN 'ON'
ELSE 'OFF'
END B1,
CASE WHEN B2 = 1
THEN 'ON'
ELSE 'OFF'
END B2
FROM
DATALOGTABLE WITH (NOLOCK)
WHERE
(CONVERT(DATE, DATEANDTIME, 103) >= CONVERT(DATE, #FROMDATETIME, 103)
AND CONVERT(DATE, DATEANDTIME, 103) <= CONVERT(DATE, #TODATETIME, 103))
AND (((DATEPART(minute, dateandtime) % #intv) = 0))
UNION ALL
SELECT
DATEANDTIME, ALARMTXT ALARM,
NULL F870, NULL F872, NULL F82, NULL F810, NULL F869, NULL F874,
NULL F867, NULL F84, NULL F822, NULL F821, NULL F8X, NULL B1, NULL B2
FROM
DBO.ALARMHISTORY WITH (NOLOCK)
WHERE
(CONVERT(DATE, DATEANDTIME, 103) >= CONVERT(DATE, #FROMDATETIME, 103)
AND CONVERT(DATE, DATEANDTIME, 103) <= CONVERT(DATE, #TODATETIME, 103))
AND (((DATEPART(minute, dateandtime) % #intv) = 0))
) Z
ORDER BY
Z.DATEANDTIME DESC
In the above query I have given time interval of 300 second i.e. 5 minute means value should come after every 300 second or 5 minutes. But it is showing value of every minute.
09 Jan 2020 20:10:59 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:58 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:57 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:56 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:55 NULL 70.00 72.00 2.00 0.00 69.65
Here the first record have date '09 Jan 2020 20:10:59' and second should be
'09 Jan 2020 20:15:59' because interval given between two rows date is 300 seconds. which is not coming in this case. What to do here?
You seem try to mod minutes to seconds, you should correct this:
declare #DATETIME DATETIME = '2016-09-21 14:59:30';
declare #INTERVAL NVARCHAR(50) = '300'
select (DATEPART(minute, #DATETIME) * 60 + DATEPART(second, #DATETIME)) % #INTERVAL;
I'm using SQL server 2008 and don't know where to even begin this calculation. I would really appreciate any help you can provide.
I have two columns, StartTime and EndTime. I have three time ranges: morning 12:00 am - 7:59 am, day 8:00 am to 3:59 (or 15:39) pm, and evening 4:00 pm (or 16:00) to 11:59 (or 23:59) pm.
I want to calculate the number of hours between the StartTime and EndTime that belong in each range. For example, for the first row below, there are 11 hours between 6:00 and 17:00, and there are 2 hours in morning, 8 hours in day, and 1 hour in evening. So I want four columns: one for the 11 hours, one each for the morning, day and evening breakout.
StartTime EndTime
2017-10-25 06:00:00.000 2017-10-25 17:00:00.000
2017-10-26 05:30:00.000 2017-10-26 18:00:00.000
2017-10-30 07:00:00.000 2017-10-30 17:30:00.000
2017-11-01 06:00:00.000 2017-11-01 17:30:00.000
2017-10-06 04:00:00.000 2017-10-06 05:00:00.000
2016-04-28 04:00:00.000 2016-04-28 10:00:00.000
2017-06-30 04:00:00.000 2017-07-01 00:00:00.000
2016-01-26 06:30:00.000 2016-01-26 19:00:00.000
2017-08-15 07:00:00.000 2017-08-15 19:30:00.000
2016-01-28 07:00:00.000 2016-01-28 19:30:00.000
Desired results, using the first one
NbrHours = 11
MorningHrs = 2
DayHrs = 8
EveningHrs = 1
Something similar to this should do the trick for you ...
drop table if exists #times;
go
create table #times(
StartTime datetime ,
EndTime datetime
);
insert #times values
('2017-10-25 06:00:00.000', '2017-10-25 17:00:00.000'),
('2017-10-26 05:30:00.000', '2017-10-26 18:00:00.000'),
('2017-10-30 07:00:00.000', '2017-10-30 17:30:00.000'),
('2017-11-01 06:00:00.000', '2017-11-01 17:30:00.000'),
('2017-10-06 04:00:00.000', '2017-10-06 05:00:00.000'),
('2016-04-28 04:00:00.000', '2016-04-28 10:00:00.000'),
('2017-06-30 04:00:00.000', '2017-07-01 00:00:00.000'),
('2016-01-26 06:30:00.000', '2016-01-26 19:00:00.000'),
('2017-08-15 07:00:00.000', '2017-08-15 19:30:00.000'),
('2016-01-28 07:00:00.000', '2016-01-28 19:30:00.000')
;
with
a as (
select StartTime ,
EndTime ,
datepart(hour, StartTime) as StartHour ,
datepart(hour, StartTime) + datediff(hour, StartTime, EndTime) as EndHour
from #times
)
select a.StartTime,
a.EndTime ,
StartHour ,
EndHour ,
EndHour - StartHour as Total ,
case when EndHour > 8 then 8 else EndHour end - case when StartHour < 0 then 0 else StartHour end as Morning ,
case when EndHour > 16 then 16 else EndHour end - case when StartHour < 8 then 8 else StartHour end as Afternoon ,
case when EndHour > 24 then 24 else EndHour end - case when StartHour < 16 then 16 else StartHour end as Evening
from a
;
In SQL Server, I have a table of processes with a starttime and an endtime, from which I can calculate a duration using 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
How can I select the timespan of the process duration that occured in specific hours of the day (11 and 12) in seconds?
So process1 would be 10 minutes in hour 11.
process2 would be 20 minutes in hour 11, 30 minutes in hour 12.
Here's a sample that will generate hourly records for each source record. It uses a recursive CTE to move from the StartTime of each record through the EndTime. It may need some slight modifications to make it work in your case, but hopefully you can get the idea of how this method works.
Note that, as shown in the sample below, this will work properly even if the time span crosses a date boundary.
--==================================================================================
-- 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;
The output from the above sample would look like this:
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
To handle general cases, you could try something like
--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;
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
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
With timeDifference -
SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,StartTime,EndTime),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference
from #YourTableName
With Days and 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
I think this does the trick, but it's pretty ugly. Maybe someone can do it more elegantly?
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
I'm working on a Room Scheduling application. We have this Room Check Out Rule that we need follow. All
room check out should be 12:00 PM. If the check out date is after 12.00 PM it will be considered additional 1 day.
Below is my T-SQL code that returns 5 days.
SELECT DATEDIFF(day, '3/12/2013 12:00:00 PM', '3/17/2013 3:00:00 PM');
If you see the code above the end date is 3:00:00 PM. How can I tweak this code to return 6 days instead of 5?
What if I have this code?
SELECT CEILING(DATEDIFF(SECOND, '3/12/2013 02:00:00 PM' , '3/17/2013 12:50:36 PM') / (24.0 * 60 * 60))
The above code still returns 5 days instead of 6.
SELECT CEILING(DATEDIFF(SECOND, '3/12/2013 12:00:00 PM', '3/17/2013 12:00:01 PM') / (24.0 * 60 * 60))
The correct way is to subtract 12 hours from StartDate and EndDate, then take a day-diff + 1:
declare #dateStart as datetime, #dateEnd as datetime
set #dateStart = cast('20130301 11:59:59 AM' as datetime)
set #dateEnd = cast('20130301 12:01:01 PM' as datetime)
select
#dateStart,
#dateEnd
select days = 1 + datediff(d,#dateStart,#dateEnd)
select
days = 1 + datediff(d, dateadd(hh, -12, #dateStart), dateadd(hh, -12, #dateEnd))
returns this:
----------------------- -----------------------
2013-03-01 11:59:59.000 2013-03-01 12:01:01.000
days
-----------
1
days
-----------
2
Clearly the second formula is correct, not the first.
Perhaps you can count hours:
SELECT DATEDIFF(hour, '3/12/2013 12:00:00 PM', '3/17/2013 3:00:00 PM');
Therefore, 123 > 120 (or divided by 24 - 5.125 > 5) accounts for 6 days.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I need to create a query to sum day's hours and night's hours from a range intersec.
For example with this range:
8AM-8PM -> day
8PM-8AM -> night
and one or more start-end time period:
7.30AM 10.00PM
I would like to get this values:
12 day's hours
2.5 night's hours
I don't know which is the bast way to accomplish this function.
As i wrote in my comment, it is a brain teaser. I hope you can combine this with your code.
declare #t table(datefrom smalldatetime, dateto smalldatetime)
insert #t values('2012-01-01 10:30', '2012-01-02 09:00')
insert #t values('2012-01-01 08:00', '2012-01-02 20:20')
insert #t values('2012-01-01 19:00', '2012-01-02 13:00')
insert #t values('2012-01-01 20:00', '2012-01-02 00:00')
insert #t values('2012-01-01 23:00', '2012-01-03 00:00')
select datefrom, dateto, day, cast(datediff(minute, datefrom, dateto)/60.0 - day as decimal(9,2)) night
from #t t
cross apply
(select dateadd(day, datediff(hour, '1900-01-01 20:00', datefrom)/24, '1900-01-02 08:00') a,
dateadd(day, datediff(hour, '1901-01-01 09:00', dateto)/24, '1901-01-01 20:00' ) b) c
cross apply
(select cast(((datediff(hour, a, b) - 12 * datediff(day, a,b)) * 60
+case when a < datefrom then -datediff(minute, a, datefrom) else 0 end
+case when b > dateto then +datediff(minute, b, dateto) else 0 end) / 60.0 as decimal(9,2)) day) e
Result:
datefrom dateto day night
2012-01-01 10:30 2012-01-02 09:00:00 10.50 12.00
2012-01-01 08:00 2012-01-02 20:20:00 24.00 12.33
2012-01-01 19:00 2012-01-02 13:00:00 6.00 12.00
2012-01-01 20:00 2012-01-02 00:00:00 0.00 4.00
2012-01-01 23:00 2012-01-03 00:00:00 12.00 13.00
Sorry for adding another answer. But i realized that it seems you only handle time, my other solution operates on several days. Here is a solution that handle time only:
declare #t table(timefrom time(0), timeto time(0))
insert #t values('10:30', '21:30')
insert #t values('07:00', '20:20')
insert #t values('19:00', '21:00')
insert #t values('00:00', '23:59')
insert #t values('00:00', '00:00')
select timefrom, timeto,
cast(dayminutes/60.0 as decimal(5,2)) [day hours]
,cast((datediff(minute, timefrom, timeto) - a.dayminutes)/60.0 as decimal(5,2)) [night hours]
from #t
cross apply
(select datediff(minute, case when timefrom > '08:00' then timefrom else '08:00' end
,case when timeto < '20:00' then case when
timeto < '08:00' then '08:00' else timeto end else '20:00' end ) dayminutes) a
Result:
timefrom timeto day hours night hours
10:30:00 21:30:00 9.50 1.50
07:00:00 20:20:00 12.00 1.33
19:00:00 21:00:00 1.00 1.00
00:00:00 23:59:00 12.00 11.98
00:00:00 00:00:00 0.00 0.00