【问题标题】:Transform JSON field with MySQL使用 MySQL 转换 JSON 字段
【发布时间】:2021-11-30 15:43:07
【问题描述】:

我在 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 来生成一个表,在该表中我可以测量从一种状态变为另一种状态所需的时间?像这样:

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)进行分组,这样我就可以有一个指标来计算从特定状态变为另一个状态所需的平均时间。

【问题讨论】:

    标签: mysql arrays mysql-json


    【解决方案1】:
    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

    【讨论】:

    • 解决了问题,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 2021-08-14
    • 2020-05-03
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多