sql 加入:检测变化

sql join: Detect changes

我想定期比较全局 sql table(称为 "resource")与本地备份(称为 "region_db")以查看某个字段是否具有被改变了。我以这种方式监视的字段称为 "state",主键称为 "id"。目前我正在做

SELECT id, state FROM resource

然后在循环中手动遍历生成的行。对于每个 (id, state) 元组,我做

SELECT state FROM region_db WHERE id = id

并检查本地 region_db 中的状态是否与全局资源数据库中的状态匹配。我能够通过这种方式检测到两种情况:1) 将新 ID 添加到资源时,以及 2) 现有行的状态发生变化时。

但是,我错过了从资源中删除一行的情况 table。

我正在考虑使用 JOIN,但不确定如何在最小化 JOIN/DB 数量的同时有效区分这三种情况(修改现有、添加新行和从资源中删除行 table)操作。

您可以使用 full join:

select coalesce(r.id, reg.id) as id,
       (case when r.id is null then 'DELETED'
             when reg.id is null then 'CREATED'
             else 'UPDATED'
        end)
from resource r full join
     region_db reg
     on r.id = reg.id
where r.id is null or reg.id is null or r.state <> reg.state;  -- something changed
WITH joined AS (
  SELECT
    region.state as 'region_state',
    resource.state as 'global_state'
  FROM
    resource
  INNER JOIN
    region_db
  ON
    resource.id = region_db.id
) SELECT * FROM joined WHERE region_state <> 'global_state';

;

此查询将为您提供一个 table,它反映了现有行的状态何时更改。如果您在 with 查询中执行 left join 而不是 inner join,您将获得可能已添加但尚未备份到 region_db 的记录。 Like-wise,使用 right join,您可能会得到已删除但尚未传播的记录。

希望这对您有所帮助。

您可以使用 UNION ALL 来告诉您表中的差异 - 基本上是检查 count(*) = 1 的位置,这意味着行不匹配的位置(因为 GROUP BY)

SELECT id,state
FROM (
    SELECT id, state FROM resource
    UNION ALL
    SELECT id,state FROM region_db
    ) tbl
GROUP BY id, state 
HAVING count(*) = 1 
ORDER BY id;