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;
我想定期比较全局 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;