DateDiff NIGHTMARE - sql

seconfHere is an example:
ID Datetime1 datetime2 (Results needed)
1 1/1/2010 7:54 1/2/2010 6:54 23
1 1/1/2010 7:54 1/4/2010 6:54 48
1 1/1/2010 7:54 1/5/2010 6:54 24
2 1/5/2010 11:00 1/8/2010 11:00 72
3 1/30/2010 23:05 2/1/2010 22:05 47
notice ID 1 in the first row it did a normal datediff but in the second and third row I need it to use the startdate of datetime2 and enddate of datetime2 of thee same ID.
turnaround time column is what is the output column I need, I only tried normal datediff but it just calculates the difference between datetime1 and datetime2. my problem is that it can be many IDs with a value of 1, so I need the datediff to dynamically update the startdate if another enddate exist for the same ID.
Im' working in a RDBMS 'Microsoft SQL server'
the code i tried is as followed:
select
*
,datediff(hh,datetime1,datetime2) as 'Turnaround time'
from
my_table
order by datetime1 asc
i hope this clears it out a little bit.
thank you in advance

the answer was Lead and Lag functions URL below:
https://www.databasejournal.com/features/mssql/lead-and-lag-functions-in-sql-server-2012.html

Related

Get timestamp of minimum value

Could someone help me with this problem;
I have a table with a Value associated with a point_id and a timestamp.
tData
timestamp
point_id
Value
2022-10-28 08:00:00
carrots
8
2022-10-28 08:00:00
cabbage
6
2022-10-28 08:00:00
screw
255
2022-10-28 08:00:04
carrots
9
2022-10-28 08:05:11
cabbage
15
2022-10-28 08:55:16
screw
270
I have another table in which I have the point_id that I want to extract to transfert to another table
tDefAvgMinMax
point_id
carrots
cabbage
Lastly I have a table that looks like this
tReportAvgMinMax
Date
point_id
average
minimum
maximum
<value>
<value>
<value>
<value>
<value>
I run this query in order to extract the average, minimum and maximum and transfer it to the last table:
INSERT INTO tReportAvgMinMax (Date, point_id, average, minimum, maximum)
SELECT #Date, Def.point_id, AVG(T._VAL), MIN(T._VAL), MAX(T._VAL)
FROM tData T
RIGH JOIN tDefAvgMinMax Def
ON T.point_id = Def.point_id
WHERE T.Timestamp BETWEEN (CAST(#Date as datetime) + '00:00:00') AND (CAST(#Date as datetime) + '23:59:59")
GROUP BY def.point_id
This is working fine so far.
Now I need to add the timestamp of the minimum value and maximum value in the table tReportAvgMinMax. I tried different approach but I can't seem to get it to work. How can I acheive this?
Point_ID
Average
Timestamp_min
Minimum
Timestamp_max
Maximum
carrots
8.5
2022-10-28 08:00:00
8
2022-10-28 08:00:04
9
cabbage
10.5
2022-10-28 08:00:00
6
2022-10-28 08:05:11
15
Thank you
I tried to use a substatement like
SELECT Def.point_id, (SELECT ...) TimestampMin, MIN(T._VAL)
but the query is taking too long and does not give me the correct result.
I also tried with a LEFT JOIN and a ORDER BY to get the lowest value and return the timestamp but that gives me only the first point_id and the query is taking a long time to run

Access Query: Match Two FKs, Select Record with Max (Latest) Time, Return 3d Field From Record

I have an Access table (Logs) like this:
pk
modID
relID
DateTime
TxType
1
1234
22.3
10/1/22 04:00
1
2
1234
23.1
10/10/22 06:00
1
3
1234
23.1
10/11/22 07:00
2
4
1234
23.1
10/12/22 08:00
3
5
4321
22.3
10/2/22 06:00
7
6
4321
23.1
10/10/22 06:00
1
7
4321
23.1
10/11/22 07:30
3
Trying to write a query as part of a function that searches this table:
for all records matching a given modID and relID (e.g. 1234 and 23.1),
picks the most recent one (the MAX of DateTime),
returns the TxType for that record.
However, a bit new to Access and its query structure is vexing me. I landed on this but because I have to include a Total/Aggregate function for TxType I had to either choose Group By (not what I want) or Last (closer, but returns junk results). The SQL for my query is currently:
SELECT Last(Logs.TxType) AS LastOfTxType, Max(Logs.DateTime) AS MaxOfDateTime
FROM Logs
GROUP BY Logs.dmID, Logs.relID
HAVING (((Logs.dmID)=[EnterdmID]) AND ((Logs.relID)=[EnterrelID]));
It returns the TxType field when I pass it the right parameters, but not the correct record - I would like to be rid of the Last() bit but if I remove it Access complains that I don't have it as part of an aggregate function.
Anyone that can point me in the right direction here?
Have you tried
SELECT TOP 1 TxtType
FROM Logs
WHERE (((Logs.dmID)=[EnterdmID]) AND ((Logs.relID)=[EnterrelID]))
ORDER BY DateTime DESC;
That will give you the latest single data row based on your DateTime field and other criteria.

GROUP BY several hours

I have a table where our product records its activity log. The product starts working at 23:00 every day and usually works one or two hours. This means that once a batch started at 23:00, it finishes about 1:00am next day.
Now, I need to take statistics on how many posts are registered per batch but cannot figure out a script that would allow me achiving this. So far I have following SQL code:
SELECT COUNT(*), DATEPART(DAY,registrationtime),DATEPART(HOUR,registrationtime)
FROM RegistrationMessageLogEntry
WHERE registrationtime > '2014-09-01 20:00'
GROUP BY DATEPART(DAY, registrationtime), DATEPART(HOUR,registrationtime)
ORDER BY DATEPART(DAY, registrationtime), DATEPART(HOUR,registrationtime)
which results in following
count day hour
....
1189 9 23
8611 10 0
2754 10 23
6462 11 0
1885 11 23
I.e. I want the number for 9th 23:00 grouped with the number for 10th 00:00, 10th 23:00 with 11th 00:00 and so on. How could I do it?
You can do it very easily. Use DATEADD to add an hour to the original registrationtime. If you do so, all the registrationtimes will be moved to the same day, and you can simply group by the day part.
You could also do it in a more complicated way using CASE WHEN, but it's overkill on the view of this easy solution.
I had to do something similar a few days ago. I had fixed timespans for work shifts to group by where one of them could start on one day at 10pm and end the next morning at 6am.
What I did was:
Define a "shift date", which was simply the day with zero timestamp when the shift started for every entry in the table. I was able to do so by checking whether the timestamp of the entry was between 0am and 6am. In that case I took only the date of this DATEADD(dd, -1, entryDate), which returned the previous day for all entries between 0am and 6am.
I also added an ID for the shift. 0 for the first one (6am to 2pm), 1 for the second one (2pm to 10pm) and 3 for the last one (10pm to 6am).
I was then able to group over the shift date and shift IDs.
Example:
Consider the following source entries:
Timestamp SomeData
=============================
2014-09-01 06:01:00 5
2014-09-01 14:01:00 6
2014-09-02 02:00:00 7
Step one extended the table as follows:
Timestamp SomeData ShiftDay
====================================================
2014-09-01 06:01:00 5 2014-09-01 00:00:00
2014-09-01 14:01:00 6 2014-09-01 00:00:00
2014-09-02 02:00:00 7 2014-09-01 00:00:00
Step two extended the table as follows:
Timestamp SomeData ShiftDay ShiftID
==============================================================
2014-09-01 06:01:00 5 2014-09-01 00:00:00 0
2014-09-01 14:01:00 6 2014-09-01 00:00:00 1
2014-09-02 02:00:00 7 2014-09-01 00:00:00 2
If you add one hour to registrationtime, you will be able to group by the date part:
GROUP BY
CAST(DATEADD(HOUR, 1, registrationtime) AS date)
If the starting hour must be reflected accurately in the output (as 9, 23, 10, 23 rather than as 10, 0, 11, 0), you could obtain it as MIN(registrationtime) in the SELECT clause:
SELECT
count = COUNT(*),
day = DATEPART(DAY, MIN(registrationtime)),
hour = DATEPART(HOUR, MIN(registrationtime))
Finally, in case you are not aware, you can reference columns by their aliases in ORDER BY:
ORDER BY
day,
hour
just so that you do not have to repeat the expressions.
The below query will give you what you are expecting..
;WITH CTE AS
(
SELECT COUNT(*) Count, DATEPART(DAY,registrationtime) Day,DATEPART(HOUR,registrationtime) Hour,
RANK() over (partition by DATEPART(HOUR,registrationtime) order by DATEPART(DAY,registrationtime),DATEPART(HOUR,registrationtime)) Batch_ID
FROM RegistrationMessageLogEntry
WHERE registrationtime > '2014-09-01 20:00'
GROUP BY DATEPART(DAY, registrationtime), DATEPART(HOUR,registrationtime)
)
SELECT SUM(COUNT) Count,Batch_ID
FROM CTE
GROUP BY Batch_ID
ORDER BY Batch_ID
You can write a CASE statement as below
CASE WHEN DATEPART(HOUR,registrationtime) = 23
THEN DATEPART(DAY,registrationtime)+1
END,
CASE WHEN DATEPART(HOUR,registrationtime) = 23
THEN 0
END

conversion of time into minute count

Ok so I need to convert a value from a table into an absolute minute count.
What I mean by that is this.
I currently have data like this
ID day time
1 1 00:04
2 1 01:08
3 2 00:08
4 2 02:04
I want it to convert to total count of minutes, not resettting back to zero for each day. so it would be
ID day time
1 1 04
2 1 68
3 2 1448
4 2 1564
Currently the time data is varchar(5) and not in date time. I have tried
DATEDIFF(MINUTE, DATEADD(DAY, DATEDIFF(DAY, 0,dispatchday), 0), dispatchday)
and that returned nothing but zero's
SQL Server I presume? This should take care of it. It doesn't make a difference what kind of field time is in, as long as it contains a valid time value.
select (day-1) * 1440 + datediff(minute, '00:00:00', time) as result from yourtable

How to convert second into datetime's 108 format hh:mm:ss in sql server without writing function

select v1.*, datediff(ss,v1.dateofchange,v2.dateofchange) as acutaltime
from vActualTime v1 left join vActualTime v2
on v1.rowno=v2.rowno-1
FK_PatientId FK_Status_PatientId DateofChange rowno acutaltime
------------ ------------------- ----------------------- -------------------- -----------
3 16 2010-08-02 15:43:46.000 1 757
3 24 2010-08-02 15:56:23.000 2 96
3 26 2010-08-02 15:57:59.000 3 NULL
I am using Sql server 2005
When I writes this
select v1.*, datediff(mi,v1.dateofchange,v2.dateofchange) as acutaltime,
convert(datetime,datediff(mi,v1.dateofchange,v2.dateofchange),108) as [date]
from vActualTime v1 left join vActualTime v2
on v1.rowno=v2.rowno-1
I gets this
FK_PatientId FK_Status_PatientId DateofChange rowno acutaltime date
------------ ------------------- ----------------------- -------------------- ----------- -----------------------
3 16 2010-08-02 15:43:46.000 1 13 1900-01-14 00:00:00.000
3 24 2010-08-02 15:56:23.000 2 1 1900-01-02 00:00:00.000
3 26 2010-08-02 15:57:59.000 3 NULL NULL
This should have been given as 00-00-000 00:13:00:0000
From what I understand you need to take your calculated minutes (the datediff you're doing) and display that in a time format 108.
This should convert the minutes to a datetime format of 108, i.e. hh:mm:ss
select convert(varchar
,dateadd(minute
, datediff(mi,v1.dateofchange,v2.dateofchange), '00:00:00')
, 108
)
Short answer: You can't.
Long answer:
First, the calculated value in minutes is interpreted as days in the CONVERT function. You'd need to divide by (24 * 60) to actually add minutes.
DATETIME only covers the years 1753 to 9999 (MSDN). Note the statement
Microsoft® SQL Server™ rejects all values it cannot recognize as dates between 1753 and 9999.
Even if you use DATETIME2 (requiring SQL Server 2008?), your date intervall only starts with the year 1. (MSDN)
Sql2008 adds a new data type called TIME, which might solve your problem.