Calculating time between entries in sql - sql

Guys i have a table that has a column named time. It capture the time of each record entry in to the database. I want to query and return another column displaying the duration between one entry and the entry before it. Example, if i store record for john today at 12:00 pm, and then Ali at 1:10 pm, i want another column that will show 01:10:00 (i.e HH:MM:SS).
I understand i can query each column number as follows.
SELECT ROW_NUMBER() OVER (ORDER BY [followuptime]) from [dbo].[FollowUp] .
i wanted to query the max row number AS follows but it fails and return error "windowed...."
SELECT MAX(ROW_NUMBER() OVER (ORDER BY [followuptime])) from [dbo].[FollowUp] .
I wanted to use the DATEDIFF(interval,start_time,end_time); function of sql , but as it is now, I am stuck. Please would appreciate your help or any alternative.

Since SQL-Server 2008R2 does not support LAG/LEAD you will need to do a self join using row_number to get the time from previous row:
WITH OrderedResults AS
( SELECT [id],
[followuptime],
[remark],
RowNumber = ROW_NUMBER() OVER (ORDER BY [followuptime])
FROM [dbo].[FollowUp]
)
SELECT a.ID,
a.FollowUpTime,
a.Remark,
PreviousTime = b.FollowUpTime,
MinutesDifference = DATEDIFF(MINUTE, b.FollowUpTime, a.FollowUpTime)
FROM OrderedResults a
LEFT JOIN OrderedResults b
ON b.RowNumber = a.RowNumber - 1
ORDER BY a.FollowUpTime;
Example on SQL Fiddle

You may not apply MAX to ROW_NUMBER. Use a CTE and query that.
;WITH MyCTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY [followuptime]) AS RowNum
FROM [dbo].[FollowUp]
)
SELECT MAX(RowNum)
FROM MyCTE

Related

Find the second largest value with Groupings

In SQL Server, I am attempting to pull the second latest NOTE_ENTRY_DT_TIME (items highlighted in screenshot). With the query written below it still pulls the latest date (I believe it's because of the grouping but the grouping is required to join later). What is the best method to achieve this?
SELECT
hop.ACCOUNT_ID,
MAX(hop.NOTE_ENTRY_DT_TIME) AS latest_noteid
FROM
NOTES hop
WHERE
hop.GEN_YN IS NULL
AND hop.NOTE_ENTRY_DT_TIME < (SELECT MAX(hope.NOTE_ENTRY_DT_TIME)
FROM NOTES hope
WHERE hop.GEN_YN IS NULL)
GROUP BY
hop.ACCOUNT_ID
Data sample in the table:
One of the "easier" ways to get the Nth row in a group is to use a CTE and ROW_NUMBER:
WITH CTE AS(
SELECT Account_ID,
Note_Entry_Dt_Time,
ROW_NUMBER() OVER (PARTITION BY AccountID ORDER BY Note_Entry_Dt_Time DESC) AS RN
FROM dbo.YourTable)
SELECT Account_ID,
Note_Entry_Dt_Time
FROM CTE
WHERE RN = 2;
Of course, if an ACCOUNT_ID only has 1 row, then it will not be returned in the result set.
The OP's statement "The row will not always be 2." from the comments conflicts with their statement "I am attempting to pull the second latest NOTE_ENTRY_DT_TIME" in the question. At a best guess, this means that the OP has rows with the same date, that could be the "latest" date. If so, then would simply need to replace ROW_NUMBER with DENSE_RANK. Their sampple data, however, doesn't suggest this is the case.
You can use window functions:
select *
from (
select
n.*,
row_number() over(partition by account_id order by note_entry_dt_time desc) rn
from notes n
) t
where rn = 2

how to get latest date column records when result should be filtered with unique column name in sql?

I have table as below:
I want write a sql query to get output as below:
the query should select all the records from the table but, when multiple records have same Id column value then it should take only one record having latest Date.
E.g., Here Rudolf id 1211 is present three times in input---in output only one Rudolf record having date 06-12-2010 is selected. same thing with James.
I tried to write a query but it was not succssful. So, please help me to form a query string in sql.
Thanks in advance
You can partition your data over Date Desc and get the first row of each partition
SELECT A.Id, A.Name, A.Place, A.Date FROM (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Date DESC) AS rn
FROM [Table]
) A WHERE A.rn = 1
you can use WITH TIES
select top 1 PERCENT WITH TIES * from t
order by (row_number() over(partition by id order by date desc))
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=280b7412b5c0c04c208f2914b44c7ce3
As i can see from your example, duplicate rows differ only in Date. If it's a case, then simple GROUP BY with MAX aggregate function will do the job for you.
SELECT Id, Name, Place, MAX(Date)
FROM [TABLE_NAME]
GROUP BY Id, Name, Place
Here is working example: http://sqlfiddle.com/#!18/7025e/2

Duration between 2 dates based on another column

I currently have a table of data that shows different steps in a process, with a date/time each step was carried out.
enter image description here
What I'm looking to do is add a column that calculates the time in minutes between each step, however it has to relate to the claimID, so in the image shown I would be looking for difference between each step for the top 4 results (as they share the same claimID), then the following 6 results, etc.
Can anyone help? I'm using SQL Server
Depending on what version of SQL Server you are using you can either use a self join or the lag window function (this should work in SQL Server 2012+):
select
claimid
, statusid
, statussetdate
, coalesce(datediff(minute,
lag(statussetdate) over (partition by claimid order by statussetdate),
statussetdate
),0) as diff_in_minutes
from
your_table
order by
ClaimID
, StatusSetDate;
You can self join the table to itself using the Row_number to get the previous date and do a DateDiff on the 2 values..
;WITH cte AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY ClaimID ORDER BY StatusSetDate) Rn
FROM ClaimStatus
)
SELECT curr.*,
ISNULL(DATEDIFF(minute, prev.StatusSetDate, curr.StatusSetDate),0)
FROM cte curr
LEFT JOIN cte prev ON curr.ClaimID = prev.ClaimID AND curr.Rn = prev.Rn + 1
ORDER BY curr.ClaimID, curr.StatusSetDate

SQL: Records on same day but different time

Sample data:
2015-10-09 17:06:54
2015-01-05 11:04:12
2015-01-05 11:04:13
2015-01-09 14:52:19
Hi, I am trying to get a list of records of date + time with a condition: If same date, get the earliest record.
I know this can be easily done by substr() to only the date, but I do need the time too.
Please see the data above: I do not want the 3rd record down because it is a duplicate date but a later time.
How should I do this? Thanks so much for your help!
In MS SQL 2005+, you can try this:
SELECT *
FROM (
SELECT *,
RANK() OVER(PARTITION BY CAST(DateTime_Column AS DATE) ORDER BY DateTime_Column DESC) AS R
FROM Your_Table) AS Tb
WHERE R = 1
If you want to select 1 row for each day, you can use ROW_NUMBER() instead of RANK()
In Oracle, you can change CAST(DateTime_Column AS DATE) to TRUNC(DateTime_Column)
This will display row with later date_time for a specific date.
SELECT T1.*
FROM
table T1 INNER JOIN table T2
ON DATE(T1.date_time) = DATE(T2.date_time)
AND T1.date_time > T2.date_time GROUP BY DATE(T1.date_time)
Hope this helps..

One row of data for a max date only - transact SQL

I am trying to select the max dates on a field with other tables, to only give me one distinct row for the max date and not other rows with other dates. the code i have for max is
SELECT DISTINCT
Cust.CustId,
LastDate=(Select Max(Convert(Date,TreatmentFieldHstry.TreatmentDateTime))
FROM TreatmentFieldHstry
WHERE Cust.CustSer = Course.CustSer
AND Course.CourseSer = Session.CourseSer
AND Session.SessionSer = TreatmentFieldHstry.SessionSer)
This gives multiple rows depending on how many dates - i just want one for the max - can anyone help with this?
Thanks
You didn't specify exactly what database and version you're using - but if you're on SQL Server 2005 or newer, you can use something like this (a CTE with the ROW_NUMBER ranking function) - I've simplified it a bit, since I don't know what those other tables are that you have in your select, that don't ever show up in any of the SELECT column lists.....
;WITH TopData AS
(
SELECT c.CustId, t.TreatmentDateTime,
ROW_NUMBER() OVER(PARTITION BY c.CustId ORDER BY t.TreatmentDateTime DESC) AS 'RowNum'
FROM
dbo.TreatmentFieldHstry t
INNER JOIN
dbo.Customer c ON c.CustId = t.CustId -- or whatever JOIN condition you have
WHERE
c.CustSer = Course.CustSer
)
SELECT
*
FROM
TopData
WHERE
RowNum = 1
Basically, the CTE (Common Table Expression) partitions your data by CustId and order by TreatmentDateTime (descending - newest first) - and numbers every entry with a consecutive number - for each "partition" (e.g. for each new value of CustId). With this, the newest entry for each customer has RowNum = 1 which is what I use to select it from that CTE.