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