我遇到了下面的表结构,我需要对它执行某种类型的查询。
最后三个字段用于审计跟踪。有一个约定:所有原始条目的值为“audit_parent_id”的值为“0”,“audit_entry_type”的值为“master”。所有修改的条目都具有audit_parent_id的父ID的值和“audit_entry_type”的值“modified”。
现在我想要做的是能够获得字段的原始值和修改后的值,并且我想用尽可能少的查询来实现。
有什么想法吗?谢谢。
答案 0 :(得分:1)
假设一个简单的案例,当您想要获取ID为50的记录的最新地址值更改时,此查询符合您的需求。
select
p.id,
p.adress as original_address,
(select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1) as latest_address
from
persons p -- Assuming it's the table name
where
p.id = 50
但是,假设即使address
值在一次审核与另一次审核之间没有变化,它在字段中保持不变。
这是另一个例子,显示所有有地址变化的人:
select
p.id,
p.adress as original_address,
(select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1) as latest_address
from
persons p -- Assuming it's the table name
where
p.audit_parent_id = 0
and
p.adress not like (select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1)
答案 1 :(得分:0)
这可以使用WITH RECURSIVE
在现代Postgres中使用纯SQL来解决。
对于 PostgreSQL 8.3 ,这个plpgsql函数可以完成工作,同时它也是现代PostgreSQL的一个不错的解决方案。你想... ..
获取字段的原始值和修改值
演示选择first_name
提交:
CREATE OR REPLACE FUNCTION f_get_org_val(integer
, OUT first_name_curr text
, OUT first_name_org text) AS
$func$
DECLARE
_parent_id int;
BEGIN
SELECT INTO first_name_curr, first_name_org, _parent_id
first_name, first_name, audit_parent_id
FROM tbl
WHERE id = $1;
WHILE _parent_id <> 0
LOOP
SELECT INTO first_name_org, _parent_id
first_name, audit_parent_id
FROM tbl
WHERE id = _parent_id;
END LOOP;
END
$func$ LANGUAGE plpgsql;
COMMENT ON FUNCTION f_get_org_val(int) IS 'Get current and original values for id.
$1 .. id';
呼叫:
SELECT * FROM f_get_org_val(123);
这假设所有树都有一个parent_id = 0
的根节点。没有循环引用,或者你最终会得到一个无限循环。您可能希望添加计数器并在x次迭代后退出循环。