Let's suppose that some event started on 1st January 2000 and is repeated every 36 hours and 45 minutes.
At this moment at my place it is 4th April 2018 18:30.
How could I calculate in SQL
date and time of last recent happening of my event
date and time of next future happening of my event ?
My first idea was adding my period in a loop to a start date until required date is reached but that would be very ineffective with longer time spans, I believe
Thank you for any help.
We could parameterize an sql statement with the results of this integer math...
int now = current time in minutes after 1 Jan, 2000
int period = 36 * 60 + 45
int eventsBeforeNow = now / period /* where '/' is a truncating, integer divide */
int lastEventTime = eventsBeforeNow * period
int nextEventTime = lastEventTime + period
Okay, I found the answer myself. Seems to work
declare #minutes int,#n int,#period int
SET #period=36*60+45
select #minutes=datediff(minute,'2000-01-01 00:00:00','2018-04-04 18:30:00')
set #n=#minutes/#period
select DATEADD(minute,#n*#period,'2000-01-01 00:00:00')
select DATEADD(minute,(#n+1)*#period,'2000-01-01 00:00:00')
Recent time of my example event is 2018-04-04 14:15:00.000
Next time of my example event is 2018-04-06 03:00:00.000
Related
I've a PSQL table like this:
Order
Start_Hour
Start_Minute
Finish_Hour
Finish_Minute
10
10
15
12
15
10
12
15
14
15
10
16
00
17
00
And I need to calculate by a query the total time expressed in hours that I spent to finish the order. In this scenario I expect to have a total of 5 hours:
12:15 - 10:15 = 2 hours
14:15 - 12:15 = 2 hours
17:00 - 16:00 = 1 hours
The query result must be 5.
The idea was concatenate start hour/minute and finish hour/minute, convert them to hour, make the difference, calculating the total.
SELECT (Start_Hour & ":" & Start_Minute) as start, (Finish_Hour & ":" & Finish_Minute) as finish
FROM OrderDetails
But when I try to convert them to HH:MM using cast or convert but I got errors.
Any advice?
Thank you
This query uses make_time as Adrian Klaver suggests.
select
"Order",
sum(extract(hour from
make_time("Finish_Hour", "Finish_Minute", 0) -
make_time("Start_Hour", "Start_Minute", 0))
) as duration
from the_table
group by "Order";
However I have remarks about your data design. Hour and minute are not enough for storing time because (apart from missing precision and other reasons) the end time might be over midnight. You have a specific data type for this - timestamp. I would suggest something like
create table the_table
(
order_nr integer,
start_time timestamp,
finish_time timestamp
);
Also note that using mixed case names in Postgresql requires double-quoting.
Use make_time:
select make_time(12, 15, 0) - make_time(10, 15, 0);
?column?
----------
02:00:00
Where in your case you would substitute in Start_Hour, Start_Minute, Finish_Hour, Finish_Minute.
I have a list of schedule that looks like this
Start Time 2016-6-20 7:30AM End Time 2016-6-20 8:00AM
I want to create a query to calculate the duration between the intervals, it would work for 30 minutes but I don’t know how to create one for when it ends on 2:45 or 2:15. If I do date diff I would give me 30 minutes duration but for 2:15 or 2:45 it will not give me that
I want something to look like
7:30, Start time7:30, End Time 8:00AM, durwtion 30 minutes
8:00, Start time 8:00, End time 8:15, duration 15 minutes
do you mean something like this? fixing it up for hr:min would be a task, but minutes is easy.
declare #starttime datetime = '2016-6-20 7:30AM'
declare #endtime datetime = '2016-6-20 8:00AM'
select rtrim(datediff(minute,#starttime, #endtime)) + ' min'
edit, try this query
;with duration_dates as
(
SELECT top (100)
dateadd(minute,(datediff(minute,0,Start_Time_UTC)/ 15)*15,0) Start_Time_UTC
,dateadd(minute,(datediff(minute,0,dateadd(minute,15,End_time_UTC))/15)*15,0) End_time_UTC
--,<your id column here>
FROM EmployeeSchedules
)
SELECT
TimeInterval
,Start_Time_UTC
,End_time_UTC
,datediff(minute, Start_Time_UTC,End_time_UTC) duration
FROM Times
LEFT JOIN duration_dates ON CAST(Start_Time_UTC AS Time) = TimeInterval
I am after some guidance on the best way to get useful information out of our MIS database
Scenario:- I want to check staff utilisation by a variable period that I can drill down into. This needs to then be split into days so I can assess over a 24 hour period what was done
The table is huge and has loads of columns we need to calculate, so ideally I need to split the records that span 2 days into 2
The table has a datetimeformat field that has user [starttime], it then has a separate field that has [duration] which is in decimal hours.
So an example would be:
ID StartTime Duration Qty username
1 2016-11-24 23:00:00 2.00 1000 Joe Bloggs
In the example above Joe starts at 11pm and works till 1 am, so what I need is to somehow split this record in my query to put anything before midnight as 1 record and anything after into another This example is pretty simple as it is half/half but some might start at 10pm and finish at 6pm so I would need 2 hours and 6 hours.
Not sure on the best way to do this, my initial thoughts was to create a cte where a start time is in 1 day and if the starttime + duration was in the next day then split the record.
Not sure if there is an easier way or if anyone has had to do this before.
Any help appreciated
#Joe has the right idea, here is pseudo-SQL
SELECT ID,StartTime,Duration,Qty,username
WHERE TRUNCATE(StartTime,DAY) = TRUNCATE(StartTime + Duration hours ,DAY)
UNION
SELECT ID,StartTime, TRUNCATE(StartTime,DAY) + 1 days - StartTime hours ,Qty,username
WHERE TRUNCATE(StartTime,DAY) < TRUNCATE(StartTime+Duration hours,DAY)
UNION
SELECT ID,TRUNCATE(StartTime+Duration hour,DAY),StartTime + duration hours - DATE(StartTime+Duration),Qty,username
WHERE TRUNCATE(StartTime,DAY) < TRUNCATE(StartTime+Duration hours,DAY)
Where TRUNCATE(timestamp,DAY) truncates a timestamp to YYYY-MM-DD 00:00:00
You can multiply rows with join. Make Tally table, simple table with numbers 1, 2, 3... and do a join. I will use table starting at zero here:
CREATE TABLE Tally0 (Number INT IDENTITY(0,1) PRIMARY KEY NOT NULL);
GO
INSERT INTO Tally0 DEFAULT VALUES;
GO 10000
Now the harders part is conversion between dates and numerics:
;WITH
tmp1 AS (SELECT *,
DATEDIFF(SECOND, CONVERT(DATE, StartTime), StartTime)/3600.0
+ DATEPART(NANOSECOND, StartTime)/(3600*1000000000.0) AS startingHours
FROM Record),
tmp2 AS (SELECT *,
startingHours + Duration AS endingHours,
(startingHours + Duration)/24.0 AS endingDays
FROM tmp1)
SELECT *,
CASE WHEN Number = 0 THEN StartTime
ELSE DATEADD(DAY, Number, CONVERT(DATE, StartTime))
END AS StartTime2,
CASE WHEN Number = 0 AND 1 < endingDays THEN 24 - startingHours
WHEN Number = 0 THEN Duration
WHEN Number + 1 < endingDays THEN 24
ELSE endingHours - Number * 24
END AS Duration2
FROM tmp2
JOIN Tally0 ON Number < endingDays
For my website I must select all messages sent between midnight (the previous night) and midnight (the next night). Basically, it's a 24 hours range.
I don't know how to do that as I store the date in a timestamp format in my DB.For example, last message was posted on 2013-10-18 11:23:35.
What I want is all message posted between 2013-10-18 00:00:00 and 2013-10-18 23:59:59.
Is that possible, if yes, how could I do that ?
You can calculate the required time in T-SQL as :
-- for previous day mid night as start time
declare #start_datetime datetime,#end_datetime datetime
Select #start_datetime = DATEADD(d,0,DATEDIFF(d,0,GETDATE()))
-- for current day mid night as end time
Select #end_datetime = DATEADD(SS,86399,DATEDIFF(d,0,GETDATE()))
select #start_datetime, #end_datetime
and then use you column name to check whether it exists between these two values.
To find out what happened between DatetimeA and DatetimeB, the sql keyword between is not your friend. It generally causes one to miss records. This construct is better.
where YourDateTimeField >= StartDateTime
and YourDateTimeField < JustAfterTheEndDateTime
In your case, you can simplify it with
where YourDateTimeField >= DateA
and YourDateTimeField < TheDayAfterDateA
Using DB2 SQL
I would like to query for records since 2:00 yesterday. I want a dynamic expression that frees me from having to manually enter the current date prior to running the query. The created_datetime attribute is of timestamp dataype.
For example:
select record_key, other_stuff
from table
where created_datetime > "2 o'clock PM yesterday"
Is this kind of dynamic timestamp comparison even possible? Eventually, I'd like to be able to do a window of time, which gets complicated!
select count(1)
from table
where created_datetime between "2 o'clock PM yesterday" and "2 o'clock PM today"
I am familiar with current date, but I am trying to conceptualize how I would leverage that. The following gets me close, but it includes everything 24 hours prior to whenever the query is run.
select count(1)
from table
where created_datetime between (currentdate - 1 day) and (currentdate # 2 o'clock PM)
I know this is some pretty basic territory, and I feel guilty posting this question, but my research has not turned up anything for me so far. I appreciate every ounce of time spent on my behalf.
Try these
select record_key, other_stuff
from table
where created_datetime > CURRENT DATE - 10 HOURS
select count(1)
from table
where created_datetime between (CURRENT DATE - 10 HOURS) and (CURRENT DATE + 14 HOURS)
select count(1)
from table
where created_datetime between (CURRENT DATE - 1 DAYS) and (CURRENT DATE + 14 HOURS)
From the IBM Dev Works Library : DB2 Basics: Fun with Dates and Times
There are heaps of samples there.
E.g.
You can also perform date and time calculations using, for lack of a
better term, English:
current date + 1 YEAR
current date + 3 YEARS + 2 MONTHS + 15 DAYS
current time + 5 HOURS - 3 MINUTES + 10 SECONDS
Try this with this Timestamp option in you where clause.
Below sample to query for between last 24 hours.
select
timestamp(CURRENT date - 1 days,(CURRENT time - 24 hours)),
timestamp(CURRENT date,CURRENT time )
FROM
sysibm.sysdummy1;