使用 MySQL 转换 JSON 字段

Transform JSON field with MySQL

我在 tableA 中有一个 JSON 字段,我在其中保存一行从一种状态更改为另一种状态的时刻,

row_id state_history
1 {"2021-09-14 21:00": "State #4", "2021-09-16 21:00": "State #1", "2021-09-17 21:00": "State #6"}
... ...

是否可以在 MySQL 中使用这个 JSON 来生成一个 table,我可以在其中测量从一种状态变为另一种状态所需的时间?像这样:

row_id Initial_state Final_state Time_diff
1 State #4 State #1 2 days
1 State #1 State #6 1 day
2 State #5 State #2 1 day
2 State #2 State #1 4 days
2 State #1 State #6 1 day
... ... ... ...

请注意每行的状态数会有所不同。 时差度量单位是分钟、小时还是天并不重要。

对于状态变化部分,我尝试了以下方法,但是这样我只能得到每一行的第一个和第二个状态。我不知道如何制作时差部分。

SELECT A.row_id, A.state ->> '$[0]' AS Initial_state, A.state ->> '$[1]' AS Final_state
FROM 
(SELECT 
  row_id,
  state_history -> '$.*[0]' AS state
FROM 
  tableA) A

如果可能的话,按状态对分组(Initial_state,Final_state)这样我就可以有一个指标来平均从一个特定状态变为另一个状态所需的时间。

WITH cte1 AS (
    SELECT test.row_id, 
           jsontable.`date`, 
           JSON_UNQUOTE(JSON_EXTRACT(test.state_history, CONCAT('$."', jsontable.`date`, '"'))) state
    FROM test
    CROSS JOIN JSON_TABLE(JSON_KEYS(state_history),
                          '$[*]' COLUMNS (`date` VARCHAR(64) PATH '$')) jsontable
),
cte2 AS (
    SELECT row_id, 
           LAG(state) OVER (PARTITION BY row_id ORDER BY `date`) Initial_state,
           state Final_state,
           DATEDIFF(`date`, LAG(`date`) OVER (PARTITION BY row_id ORDER BY `date`)) Time_diff,
           `date`
    FROM cte1
)
SELECT row_id,
       CAST(Initial_state AS CHAR) Initial_state,
       CAST(Final_state AS CHAR) Final_state,
       Time_diff
FROM cte2
WHERE Initial_state IS NOT NULL
ORDER BY row_id, `date`

step-by-step fiddle