I have this table
| MachineCode | DoCreation | MachineStateCode |
|---|---|---|
| DM139 | 2024-04-03 00:32:17.377 | 99 |
| DM139 | 2024-04-03 00:32:49.080 | 0 |
| DM139 | 2024-04-03 01:51:14.427 | 99 |
| DM139 | 2024-04-03 01:51:45.643 | 0 |
| DM139 | 2024-04-03 06:07:38.357 | 3 |
| DM139 | 2024-04-03 06:07:39.043 | 0 |
| DM139 | 2024-04-03 06:23:37.433 | 100 |
| DM139 | 2024-04-03 06:23:43.697 | 0 |
| DM139 | 2024-04-03 06:24:46.153 | 1 |
| DM139 | 2024-04-03 06:25:02.467 | 0 |
| DM139 | 2024-04-03 06:46:50.410 | 100 |
| DM139 | 2024-04-03 06:47:29.247 | 0 |
| DM139 | 2024-04-03 06:47:46.397 | 100 |
| DM139 | 2024-04-03 06:53:47.160 | 0 |
| DM139 | 2024-04-03 06:59:41.633 | 1 |
| DM139 | 2024-04-03 06:59:54.550 | 0 |
| DM139 | 2024-04-03 07:00:03.203 | 1 |
| DM139 | 2024-04-03 07:00:06.437 | 0 |
| DM139 | 2024-04-03 07:00:14.247 | 1 |
| DM139 | 2024-04-03 07:00:17.683 | 2 |
| DM139 | 2024-04-03 07:00:18.153 | 1 |
| DM139 | 2024-04-03 07:00:18.840 | 2 |
| DM139 | 2024-04-03 07:00:26.860 | 1 |
| DM139 | 2024-04-03 07:00:46.387 | 2 |
each records rapresent a "change of state" of the specific machine DM139 where
- MachineCode = code of machine (nvarchar)
- DoCreation = timestamp of when the machine change its state (datetime)
- MachineStateCode = new state of the machine, where 99 = rebooting, 0 = initializing, 3 = error, 1 = starting, 2 = working and so on (int)
I need to create a new column, let's call it MachineStateCodeAdjusted where its value is equal to 3 if the previous MachineStateCode is 3 and the current MachineStateCode is not 2, otherwise it should have the current MachineStateCode value. (the next table is what I need)
| MachineCode | DoCreation | MachineStateCode | MachineStateCodeAdjusted |
|---|---|---|---|
| DM139 | 2024-04-03 00:32:17.377 | 99 | 99 |
| DM139 | 2024-04-03 00:32:49.080 | 0 | 0 |
| DM139 | 2024-04-03 01:51:14.427 | 99 | 99 |
| DM139 | 2024-04-03 01:51:45.643 | 0 | 0 |
| DM139 | 2024-04-03 06:07:38.357 | 3 | 3 |
| DM139 | 2024-04-03 06:07:39.043 | 0 | 3 |
| DM139 | 2024-04-03 06:23:37.433 | 100 | 3 |
| DM139 | 2024-04-03 06:23:43.697 | 0 | 3 |
| DM139 | 2024-04-03 06:24:46.153 | 1 | 3 |
| DM139 | 2024-04-03 06:25:02.467 | 0 | 3 |
| DM139 | 2024-04-03 06:46:50.410 | 100 | 3 |
| DM139 | 2024-04-03 06:47:29.247 | 0 | 3 |
| DM139 | 2024-04-03 06:47:46.397 | 100 | 3 |
| DM139 | 2024-04-03 06:53:47.160 | 0 | 3 |
| DM139 | 2024-04-03 06:59:41.633 | 1 | 3 |
| DM139 | 2024-04-03 06:59:54.550 | 0 | 3 |
| DM139 | 2024-04-03 07:00:03.203 | 1 | 3 |
| DM139 | 2024-04-03 07:00:06.437 | 0 | 3 |
| DM139 | 2024-04-03 07:00:14.247 | 1 | 3 |
| DM139 | 2024-04-03 07:00:17.683 | 2 | 2 |
| DM139 | 2024-04-03 07:00:18.153 | 1 | 1 |
| DM139 | 2024-04-03 07:00:18.840 | 2 | 2 |
| DM139 | 2024-04-03 07:00:26.860 | 1 | 1 |
| DM139 | 2024-04-03 07:00:46.387 | 2 | 2 |
I used the LAG function to get the previous MachineStateCode (and it works) but to work as I want I need to get the previous MachineStateCodeAdjusted, that is not accessible for the LAG function.
The SQL query I'm executing is this:
SELECT MachineCode
, DoCreation
, MachineStateCode
, IIF(LAG(MachineStateCode, 1, MachineStateCode) OVER (ORDER BY DoCreation ASC) = 3
AND MachineStateCode<>2, 3, MachineStateCode) AS MachineStateCodeAdjusted
FROM mch.MachineStateChanges
and the result I get clearly show me the it not works as I want
| MachineCode | DoCreation | MachineStateCode | MachineStateCodeAdjusted |
|---|---|---|---|
| DM139 | 2024-04-03 00:32:17.377 | 99 | 99 |
| DM139 | 2024-04-03 00:32:49.080 | 0 | 0 |
| DM139 | 2024-04-03 01:51:14.427 | 99 | 99 |
| DM139 | 2024-04-03 01:51:45.643 | 0 | 0 |
| DM139 | 2024-04-03 06:07:38.357 | 3 | 3 |
| DM139 | 2024-04-03 06:07:39.043 | 0 | 3 |
| DM139 | 2024-04-03 06:23:37.433 | 100 | 100 WRONG |
| DM139 | 2024-04-03 06:23:43.697 | 0 | 0 WRONG |
| DM139 | 2024-04-03 06:24:46.153 | 1 | 1 WRONG |
I also tried with a recursive CTE and it works but it is very slow! The query extract in 4 minutes 2 days of work, while I need to extract 1 year!
What is the best (and fast) approach to fix it?
where its value is equal to 3 if the previous MachineStateCode is 3 and the current MachineStateCode is not 2, but in your result, very many rows should have the value 3 although its previous value is not 3. So do you rather mean all rows beginning from the first row with 3 should get 3 as long as the value is not 2? By the way, which RDBMS do you use?