Calculate time between rows - sql

Table dbo.Update includes a datetime of when the update took place along with an entered by person ID.
In my result set i need to include the time of the update and who created the update but also the time since the previous update
eg;
ID Datetime Person Time Between
1 0900hrs 1 -
2 0947hrs 2 47m
3 1030hrs 1 43m
The number of rows in dbo.Update will vary and the differences could go in to days or even weeks sometimes.
I cant figure out how to do this if someone could possibly assit?
Thanks in Advance!
~D

Your syntax suggests that you are using SQL Server. In SQL Server 2012+, just use lag():
select t.*,
datediff(minute, lag(datetime) over (order by datetime), datetime) as diff_in_minutes
from t;

Related

Adding x work days onto a date in SQL Server?

I'm a bit confused if there is a simple way to do this.
I have a field called receipt_date in my data table and I wish to add 10 working days to this (with bank holidays).
I'm not sure if there is any sort of query I could use to join onto this table from my original to calculate 10 working days from this, I've tried a few sub queries but I couldn't get it right or perhaps its not possible to do this. I didn't know if there was a way to extract the 10th rowcount after the receipt date to get the calendar date if I only include 'Y' into the WHERE?
Any help appreciated.
This is making several assumptions about your data, because we have none. One method, however, would be to create a function, I use a inline table value function here, to return the relevant row from your calendar table. Note that this assumes that the number of days must always be positive, and that if you provide a date that isn't a working day that day 0 would be the next working day. I.e. adding zero working days to 2021-09-05 would return 2021-09-06, or adding 3 would return 2021-09-09. If that isn't what you want, this should be more than enough for you to get there yourself.
CREATE FUNCTION dbo.AddWorkingDays (#Days int, #Date date)
RETURNS TABLE AS
RETURN
WITH Dates AS(
SELECT CalendarDate,
WorkingDay
FROM dbo.CalendarTable
WHERE CalendarDate >= #Date)
SELECT CalendarDate
FROM Dates
WHERE WorkingDay = 1
ORDER BY CalendarDate
OFFSET #Days ROWS FETCH NEXT 1 ROW ONLY;
GO
--Using the function
SELECT YT.DateColumn,
AWD.CalendarDate AS AddedWorkingDays
FROM dbo.YourTable YT
CROSS APPLY dbo.AddWorkingDays(10,YT.DateColumn) AWD;

Grouping consequent entries subject to condition

I have this sql challenge which I would be happy to be helped with:
The challenge is: given list of transactions, I have to treat multiple transactions as if there are one, but only if the period of time between the two consequent transactions is less than 2 weeks.
For example, if a customer made 3 transactions,
the first one on 01.05.2020,
the second one on 08.05.2020
and the third one on 20.05.2020 - all the 3 should be treated as if they took place simultaneously,
Since there are less than 2 weeks between each 2 consequent entries.
If the fourth transaction took place on 20.7.2020 it should be treated separately since there are more than two weeks between this one and the previous one.
You can identify groups using lag() and a cumulative sum:
select t.*,
sum(case when prev_datetime > datetime - interval '14 day' then 0 else 1 end) over (partition by customer order by datetime) as transaction_group
from (select t.*, lag(datetime) over (partition by customer order by datetime) as prev_datetime
from t
) t;
Datetime functions are notoriously database dependent. So the exact date/time functions might be different on your database. But the idea is the same.

How can I select the difference between two rows?

Here's an example of what I'm looking for:
I have data that comes in as a lifetime total in gallons. I want to be able to display the data as a running total over the time period I am selecting for rather than as a lifetime total. For example:
timestamp lifetimeTotal runningTotal
1:30 3000 0
1:31 3001 1
1:32 3005 5
1:33 3010 10
I'm not sure how to go about doing this. I was looking at examples like this one using over but it's not quite what I'm looking for: I don't want to add the rows together every time, rather I want to add the difference between the two rows. Right now I am simply selecting the lifetime totals and displaying that.
Any ideas? I will add code if necessary but there's not much to show besides my select statement; I am having trouble thinking of a way to do this conceptually.
This should give difference between the current lifetimeTotal and the min lifetimeTotal
SELECT timestamp,
lifetimeTotal,
lifetimeTotal - MIN(lifetimeTotal) OVER () as runningTotal
FROM Table
This can be easily done using window functions:
SELECT [timestamp], lifetimeTotal,
COALESCE(SUM(diff) OVER (ORDER BY [timestamp]), 0) AS runningTotal
FROM (
SELECT [timestamp],
lifetimeTotal,
lifetimeTotal - LAG(lifetimeTotal) OVER (ORDER BY [timestamp]) AS diff
FROM mytable ) t
The above query uses LAG to calculate the difference between current and previous row. SUM OVER is then used in an outer query to calculate the running total of the difference.
Demo here

Need to decide between a trigger, CASE, END-ELSE to write to a table & DATEDIFF()

Bear with me here. I used the script found at:
http://sqlfool.com/2008/11/replication-monitor/
I want to test to see if an entry been made from the server over the last 30 minutes?
If the answer is NO, then write that entry to a different table and possibly alert us.
The following query me the difference in minutes between right now and the very last entry for the server Test1 under 'monitorDate', a datetime field.
SELECT TOP 1 DATEDIFF (minute, (SELECT TOP 1 (SELECT MAX(monitorDate)
FROM dba_replicationMonitor)), GETDATE())
FROM MASTER.dbo.dba_replicationMonitor
WHERE publicationName = 'Test1'
I can't figure out how to say 'if that number returned is more than 5, pass the serverName and monitorDate to a different table.
Any suggestions to point the way would be greatly appreciated. Thanks.
Couldn't you just derive your results and insert them if they match your needs?
INSERT INTO WHATEVERTABLE (serverfield, datefield)
SELECT result.server, result.date
FROM (YOURQUERY) result
WHERE result.yourresult > 5

how to get data whose expired within 45 days..?

HI all,
i have one sql table and field for that table is
id
name
expireydate
Now i want only those record which one is expired within 45 days or 30 days.
how can i do with sql query .?
I have not much more exp with sql .
Thanks in advance,
If you are using mysql then try DATEDIFF.
for 45 days
select * from `table` where DATEDIFF(now(),expireydate)<=45;
for 30 days
select * from `table` where DATEDIFF(now(),expireydate)<=30;
In oracle - will do the trick instead of datediff and SYSDATE instead of now().[not sure]
In sql server DateDiff is quite different you have to provide unit in which difference to be taken out from 2 dates.
DATEDIFF(datepart,startdate,enddate)
to get current date try one of this: CURRENT_TIMESTAMP or GETDATE() or {fn NOW()}
You can use a simple SELECT * FROM yourtable WHERE expireydate < "some formula calculating today+30 or 45 days".
Simple comparison will work there, the tricky part is to write this last bit concerning the date you want to compare to. It'll depend of your environment and how you stored the "expireydate" in the database.
Try Below:-
SELECT * FROM MYTABLE WHERE (expireydate in days) < ((CURRENTDATE in days)+ 45)
Do not execute directly! Depending of your database, way of obtaining a date in days will be different. Go look at your database manual or please precise what is your database.