我试图从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;