我试图从MySQL表中提取数据,并以一种日志文件格式插入到另一个表中。
比方说我有这张桌子。
表A
+--------+----+-------+-------+-------+---------+
|UniqueID|Item|ColumnA|ColumnB|ColumnC|TimeStamp|
+--------+----+-------+-------+-------+---------+
|1 | 1 | 500 | 600 | 700 | 13:01 |
|2 | 2 | 50 | 60 | 70 | 13:03 |
|3 | 3 | 17 | 18 | 19 | 13:12 |
|4 | 1 | 501 | 600 | 700 | 13:15 |
|5 | 1 | 501 | 600 | 699 | 13:18 |
|6 | 3 | 20 | 18 | 19 | 13:22 |
|7 | 1 | 501 | 600 | 702 | 13:25 |
|8 | 2 | 50 | 66 | 70 | 13:26 |
|9 | 3 | 20 | 25 | 19 | 13:32 |
+--------+----+-------+-------+-------+---------+
我有多张表,里面有不同数量的列和项目。我不介意对表名和列名进行硬编码。
我想最后得到这张表
+----+------+-------+--------+-------------+---------+
|Item|Table |Column |NewValue|PreviousValue|TimeStamp|
+----+------+-------+--------+-------------+---------+
| 1 |TableA|ColumnA| 501 | 500 | 13:15 |
| 1 |TableA|ColumnC| 699 | 700 | 13:18 |
| 3 |TableA|ColumnA| 20 | 17 | 13:22 |
| 1 |TableA|ColumnC| 699 | 702 | 13:25 |
| 2 |TableA|ColumnB| 66 | 60 | 13:26 |
| 3 |TableA|ColumnB| 25 | 18 | 13:32 |
+----+------+-------+--------+-------------+---------+
MySQL并没有让这一切变得非常容易。您可以通过计算上一个时间戳并将其加入来获得上一条记录。在MySQL 8.0中,您可以使用lag()
来实现此目的。
然后您需要取消对这些值的透视。MySQL并没有让这变得非常容易,但您可以使用cross join
和case
表达式。剩下的只是条件逻辑和过滤:
select item, 'TableA' as tableName, colname,
col as newvalue, col_prev as prevvalue, timestamp
from (select t.*, c.colname,
(case when c.colname = 'columnA' then columnA
when c.colname = 'columnB' then columnB
when c.colname = 'columnC' then columnC
end) as col,
(case when c.colname = 'columnA' then tprev.columnA
when c.colname = 'columnB' then tprev.columnB
when c.colname = 'columnC' then tprev.columnC
end) as col_prev
from (select t.*,
(select max(t2.timestamp)
from tablea t2
where t2.item = t.item and t2.timestamp < t.timestamp
) as timestamp_prev
from tablea t
) t join
t tprev
on t.item = tprev.item and t.timestamp_prev = tprev.timestamp cross join
(select 'columnA' as colname union all
select 'columnB' as colname union all
select 'columnC' as colname
) c
) ct
where col_prev <> col;