I have an audit table in a SQL database that is structured like the one below:
audit_id | id | location | location_sub | location_status | dtm_utc_action | action_type |
---|---|---|---|---|---|---|
2144 | 2105 | 9 | 1 | 1 | 2022-09-08 12:36 | i |
4653 | 2105 | 9 | 1 | 1 | 2022-09-08 13:53 | u |
7304 | 2105 | 10 | 2 | 2 | 2022-09-13 15:51 | u |
7326 | 2105 | 11 | 1 | 2 | 2022-09-14 10:06 | u |
I'm trying to write a query that will assist me in finding records from this table where the location has changed, and would like to show the ID, old location, new location and time of the change.
Based on some other questions, I've tried joining the table with itself, but I don't understand how to prevent duplication. This query below will return each record multiple times, which isn't desired.
SELECT
a.id,
a.location AS old_loc,
a.dtm_utc_action AS FirstModifyDate,
b.location AS new_loc,
b.dtm_utc_action AS SecondModifyDate
FROM
audit_table a
JOIN audit_table b ON a.id = b.id
WHERE
a.audit_id <> b.audit_id
AND
a.dtm_utc_action < b.dtm_utc_action
AND
a.location <> b.location
AND
a.id = '2105'
Would like results to look like this:
id | old_loc | new_loc | dtm_utc_action |
---|---|---|---|
2105 | 9 | 10 | 2022-09-13 15:50 |
2105 | 10 | 11 | 2022-09-14 10:06 |
Depending on your DBMS you can use a LEAD
function to retrieve the next date from the audit table
with audit_sequence as (
select *, lead(dtm_utc_action) OVER ( PARTITION BY id ORDER BY dtm_utc_action) next_update
from audit_table
)
SELECT
a.id,
a.location AS old_loc,
a.dtm_utc_action AS FirstModifyDate,
b.location AS new_loc,
b.dtm_utc_action AS SecondModifyDate
FROM
audit_table a
JOIN audit_sequence s on a.id = s.id and a.dtm_utc_action = s.dtm_utc_action
JOIN audit_table b on a.id = b.id and b.dtm_utc_action = s.next_update
WHERE
a.location <> b.location
AND
a.id = '2105'