I have table with changelog, every row give me specify inormation about actions.
Example:
- Ticket closed on 2022-06-26 14:12:07.000
- Ticket reopened on 2022-06-28 08:35:59.000
- Ticket closed on 2022-06-28 12:55:11.000
- Ticket reopened on 2022-06-30 17:04:34.000
In other table I have information about creation and closed date for tickets and for now I just make a datediff between those 2 dates. But it is not transparent for my stakeholder.
I need to count exactly number of days when ticket was opened and when it was closed from changelog.
I found similiar problems like this one
MySQL Date difference between two rows
but here is max and min but I need to count every change
Here is I think all data is needed to do this
Table
# | Created | field | fromString | toString | id |
---|---|---|---|---|---|
1 | 2022-06-20 13:08:26.000 | status | Open | Closed | 50850 |
2 | 2022-06-20 13:16:53.000 | status | Closed | Reopened | 50850 |
3 | 2022-06-20 13:27:12.000 | status | Open | Closed | 50850 |
4 | 2022-06-20 13:27:18.000 | status | Closed | Reopened | 50850 |
5 | 2022-06-20 13:37:44.000 | status | Open | Closed | 50850 |
6 | 2022-06-20 13:51:15.000 | status | Closed | Reopened | 50850 |
7 | 2022-06-21 15:40:44.000 | status | Open | Closed | 50850 |
8 | 2022-06-22 07:59:29.000 | status | Closed | Reopened | 50850 |
9 | 2022-06-22 08:04:59.000 | status | Open | Closed | 50850 |
10 | 2022-06-22 10:58:12.000 | status | Closed | Reopened | 50850 |
11 | 2022-06-22 19:27:42.000 | status | Open | Closed | 50850 |
12 | 2022-06-22 19:28:33.000 | status | Closed | Reopened | 50850 |
13 | 2022-06-22 19:29:13.000 | status | Open | Closed | 50850 |
14 | 2022-06-22 19:29:27.000 | status | Closed | Reopened | 50850 |
15 | 2022-06-23 16:24:36.000 | status | Open | Closed | 50850 |
16 | 2022-06-23 16:29:09.000 | status | Closed | Reopened | 50850 |
17 | 2022-06-23 16:30:37.000 | status | Open | Closed | 50850 |
18 | 2022-06-23 16:33:18.000 | status | Closed | Reopened | 50850 |
19 | 2022-06-23 16:33:48.000 | status | Open | Closed | 50850 |
20 | 2022-06-23 16:34:27.000 | status | Closed | Reopened | 50850 |
21 | 2022-06-23 16:34:46.000 | status | Open | Closed | 50850 |
2
Answers
You have to somehow get (log) rows containing two timestamps to do some diff the way your are doing it currently based upon that "other table".
So the base table for the query is your log table, delivering the timestamp of e.g. "ticket open" actions. Now join the same table a second time for getting the timestamp of "ticket close" actions. Join criteria is the ticket id and the closing timestamp to be the minimal but later then the opening one as well as the correct source ("open") and target stati ("close").
… resulting in some query like this (untested and column names changed for better understanding, just get the idea ):
Please be aware, that you are working on a cross product of "two" potencially large tables, that probably are not optimized for such joins. This query costs a good deal of CPU and/or RAM and should be a base for well set indices before letting loose on production.
As your sample
changelog
data starts with thestatus
change fromOpen
toClosed
, I have assumed that the initialOpen
datetime needs to come from the ticket itself.In your question you stated:
but the
number of days
between2022-06-20 13:16:53
and2022-06-20 13:27:12
is obviously 0, so in these examples I have done all calculations in seconds.If you are only doing this calculation for
Closed
tickets (so there’s aclosed
status for everyopen
/reopened
status) then you can use a simpleGROUP BY
:Another approach is to use a correlated subquery to get the
closed
time, and if the ticket is not closed use current datetime to calculate how long it has been open for:Another approach, using the LEAD() window function to get the value of
created
from the next row, and Common Table Expressions (CTEs) to split up the query: