mysql - 如何确定数据库记录之间发生了什么变化

标签 mysql database

首先假设,MySQL数据库中存在下表

|----|-----|-----|----|----|-----------|--------------|----|
| id | rid | ver | n1 | n2 | s1        | s2           | b1 |
|----|-----|-----|----|----|-----------|--------------|----|
| 1  | 1   | 1   | 0  | 1  | Hello     | World        | 0  |
| 2  | 1   | 2   | 1  | 1  | Hello     | World        | 0  |
| 3  | 1   | 3   | 0  | 0  | Goodbye   | Cruel World  | 0  |
| 4  | 2   | 1   | 0  | 0  | Hello     | Doctor       | 1  | 
| 5  | 2   | 2   | 0  | 0  | Hello     | Nurse        | 1  |
| 6  | 3   | 1   | 0  | 0  | Dippity   | Doo-Dah      | 1  |
|----|-----|-----|----|----|-----------|--------------|----|

问题

我如何编写一个查询来确定对于任何给定的 rid,最新版本和它之前的版本(如果有)之间发生了什么变化,以便它产生如下内容:

|-----|-----------------|-----------------|-----------------|
| rid | numbers_changed | strings_changed | boolean_changed |
|-----|-----------------|-----------------|-----------------|
| 1   | TRUE            | TRUE            | FALSE           |
| 2   | FALSE           | TRUE            | FALSE           |
| 3   | n/a             | n/a             | n/a             |
|-----|-----------------|-----------------|-----------------|

我认为我应该能够通过在表与其自身之间进行交叉连接来做到这一点,但我无法解决如何执行此连接以获得所需的输出。

我需要为包含 10 列和 100 条记录的 1-10 个版本(产生 1000 行)的表生成此“报告”。请注意,数据库的特定设计不是我自己设计的,并且(此时)改变数据库的结构不是可接受的方法。

输出的实际格式并不重要 - 如果它简化了查询,那么对于每个“更改集”更改的内容的“完整分割”也是可以接受的,例如

|-----|-----|-----|----|----|----|----|----|
| rid | old | new | n1 | n2 | s1 | s2 | b1 |
|-----|-----|-----|----|----|----|----|----|
| 1   | 1   | 2   | Y  | N  | N  | N  | N  |
| 1   | 2   | 3   | Y  | Y  | Y  | Y  | N  |
| 2   | 4   | 5   | N  | N  | N  | Y  | N  |
|-----|-----|-----|----|----|----|----|----|

请注意,在这种情况下也可以省略只有一个版本的删除记录,因为出于本报告的目的,我只关心已更改的记录并获取单独的记录列表没有改变是一个简单的查询

最佳答案

您可以将每一行与下一行连接起来

select *
from history h1
join history h2
  on  h2.rid = h1.rid
  and h2.id = (
    select min(h.id)
    from history h
    where h.rid = h1.rid
      and h.id > h1.id
  );

然后您只需要比较两行中的每一列,例如 h1.n1 <> h2.n1 as n1 .

完整的查询是:

select h1.rid, h1.id as old, h2.id as new
  , h1.n1 <> h2.n1 as n1
  , h1.n2 <> h2.n2 as n2
  , h1.s1 <> h2.s1 as s1
  , h1.s2 <> h2.s2 as s2
  , h1.b1 <> h2.b1 as b1
from history h1
join history h2
  on  h2.rid = h1.rid
  and h2.id = (
    select min(h.id)
    from history h
    where h.rid = h1.rid
      and h.id > h1.id
  );

结果:

| rid | old | new | n1 | n2 | s1 | s2 | b1 |
|-----|-----|-----|----|----|----|----|----|
|   1 |   1 |   2 |  1 |  0 |  0 |  0 |  0 |
|   1 |   2 |   3 |  1 |  1 |  1 |  1 |  0 |
|   2 |   4 |   5 |  0 |  0 |  0 |  1 |  0 |

演示:http://sqlfiddle.com/#!9/2e5d12/5

如果列可以包含 NULL,您可能需要像 NOT h1.n1 <=> h2.n1 as n1 这样的东西. <=>是 NULL 保存相等性检查。

如果版本在 rid 内组保证是连续的,你可以简化 JOIN 到

from history h1
join history h2
  on  h2.rid = h1.rid
  and h2.ver = h1.ver + 1

演示:http://sqlfiddle.com/#!9/2e5d12/7

关于mysql - 如何确定数据库记录之间发生了什么变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48756308/

相关文章:

Python 堆叠到非堆叠格式

database - 非归档 ORACLE DB 的表空间 PIT 恢复

database - 层次数据库(IMS DB)数据检索方式

mysql - 为什么不使用MySQL索引合并?

mysql - 我们的 MySQL 数据库应该与我们的 Apache 服务器分开吗?

MySql 显示数据类型长度

python - Python/MySQL:无数据-读取,选择或处理的零行

javascript - 在 PHP 代码中单击链接 javascript 函数调用

mysql - 我可以在触发器(mySQL)中使用嵌套的 BEGIN/END block 吗

sql-server - 字符串数据字段大小的最佳实践是什么?