【问题标题】:MySQL query to Track records from History tableMySQL 查询历史表中的跟踪记录
【发布时间】:2020-11-07 00:19:07
【问题描述】:

我需要知道 mysql 查询中的逻辑以跟踪所有更改的历史记录。下面的例子将解释我的期望。

account

+------+---------+---------------------+---------------------+
| id   | emailid | created_date        | modified_date       |
+------+---------+---------------------+---------------------+
|    1 | abc     | 2020-03-20 00:00:00 | 2020-07-10 00:00:00 |
+------+---------+---------------------+---------------------+

account_history

+------+---------+---------------------+
| id   | emailid | modified_date       |
+------+---------+---------------------+
|    1 | def     | 2020-04-03 00:00:00 |
|    1 | ghi     | 2020-05-05 00:00:00 |
|    1 | lmn     | 2020-06-05 00:00:00 |
|    1 | opq     | 2020-07-01 00:00:00 |
|    1 | opq     | 2020-07-03 00:00:00 |
|    1 | qrs     | 2020-07-10 00:00:00 |
+------+---------+---------------------+

预期结果

+------+-----------+----------+----------+-------------------+---------------------+
| id   | parameter | oldvalue | newvalue | event             | event_datetime      |
+------+-----------+----------+----------+-------------------+---------------------+
|    1 | emailid   | NULL     | def      | New Entry         | 2020-03-20 00:00:00 |
|    1 | emailid   | def      | ghi      | Change in account | 2020-04-03 00:00:00 |
|    1 | emailid   | ghi      | lmn      | Change in account | 2020-05-05 00:00:00 |
|    1 | emailid   | lmn      | opq      | Change in account | 2020-06-05 00:00:00 |
|    1 | emailid   | opq      | qrs      | Change in account | 2020-07-03 00:00:00 |
|    1 | emailid   | qrs      | abc      | Change in account | 2020-07-10 00:00:00 |
+------+-----------+----------+----------+-------------------+---------------------+

我有名为account 的主表和名为account_history 的历史表。帐户的每次更改都将在其历史表中进行跟踪,当前值将存储在历史表中。我期待我的输出是这样的。如果没有发生变化,则无需跟踪。我每天都有逻辑要跟踪。但我想跟踪过去的数据。 跟踪每日查询,

mysql>  select id,'emailid',acch.emailid as oldvalue,acc.emailid as newvalue,'Change in account',acc.modified_date from account acc join account_history acch using(id) where acc.emailid!=acch.emailid and acc.modified_date=acch.modified_date;
+------+---------+----------+----------+-------------------+---------------------+
| id   | emailid | oldvalue | newvalue | Change in account | modified_date       |
+------+---------+----------+----------+-------------------+---------------------+
|    1 | emailid | qrs      | abc      | Change in account | 2020-07-10 00:00:00 |
+------+---------+----------+----------+-------------------+---------------------+
1 row in set (0.00 sec)

感觉难以跟踪过去的数据。帮我解决这个问题。

mysql Ver 14.14 Distrib 5.7.23

即使超过 1 或 2 个查询来得出解决方案也会很有帮助。通过创建任何中间表并得出解决方案会很有帮助。

【问题讨论】:

  • 了解您正在使用的 mysql 版本会很有帮助。
  • mysql Ver 14.14 Distrib 5.7.23
  • account中modified_date的值早于account_history的最后一次更改?
  • 抱歉,打错了。会更新的
  • 我不明白为什么 def 的活动日期是 03-20 而实际上似乎是 04-03

标签: mysql mysql-workbench mysql-python


【解决方案1】:

假设我们没有能力优化表结构。因此,主要思想是执行以下操作:

  1. 将初始数据转换为修改的顺序列表。
  2. 与自己加入这个列表,其中新值记录的序列号具有下一个序列号,相对于旧值记录的序列号。

为简单起见,MySQL 5.7 的解决方案被描述为两阶段查询。这可以在 MySQL 8 中更简单地完成。此外,这不是优雅的解决方案,而是简单易懂的方法。

步骤 1. 顺序列表。

-- The variable to create sequential number
SET @rn := 0;

SELECT @rn := @rn + 1 as rn,
       ah.*
FROM (
    -- Add history record for creating new entry
    SELECT id, null as emailid, 'New Entry' as event, created_date as modified_date
    FROM account

    UNION
    -- Add intermediate history records
    -- Need grouping to filter identical values (like 'opq')
    SELECT id, emailid, 'Change in account' as event, min(modified_date) as modified_date
    FROM account_history GROUP BY id, emailid

    UNION

    -- Add history record for current value
    SELECT id, emailid, 'Change in account' as event, modified_date
    FROM account
) as ah,
  (SELECT @row := 0) as r

ORDER BY id, modified_date;

此查询产生以下列表:

rn  id  emailid  event              modified_date
 1   1  NULL     New Entry          2020-03-20 00:00:00
 2   1  def      Change in account  2020-04-03 00:00:00
 3   1  ghi      Change in account  2020-05-05 00:00:00
 4   1  lmn      Change in account  2020-06-05 00:00:00
 5   1  opq      Change in account  2020-07-01 00:00:00
 6   1  qrs      Change in account  2020-07-10 00:00:00
 7   1  abc      Change in account  2020-07-10 00:00:00

第 2 步。自连接顺序列表。

假设上面的列表被命名为subquery(子查询、视图、临时表等)。加入方式如下:

SELECT s1.id,
       'emailid' as emailid,
       s1.emailid as oldvalue,
       s2.emailid as newvalue,
       s1.event,
       s1.modified_date
FROM subquery as s1
    JOIN subquery as s2
        ON s2.id = s1.id AND s2.rn = s1.rn + 1

【讨论】:

  • 谢谢军士。这个查询非常适合我的版本。
猜你喜欢
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
  • 2023-04-06
  • 2020-10-10
  • 1970-01-01
  • 2020-11-12
相关资源
最近更新 更多