Получение оригинального и измененного контента из таблицы с контрольным журналом - PullRequest
1 голос
/ 27 марта 2012

Я наткнулся на следующую структуру таблицы, и мне нужно выполнить запрос определенного типа.

  • id
  • first_name
  • фамилия
  • адрес
  • электронная почта
  • audit_parent_id
  • Audit_entry_type
  • audit_change_date

Последние три поля предназначены для контрольного журнала. Существует соглашение, которое гласит: все исходные записи имеют значение «0» для «audit_parent_id» и значение «master» для «audit_entry_type». Все измененные записи имеют значение своего родительского идентификатора для audit_parent_id "и значение" измененного "для" audit_entry_type ".

Теперь я хочу получить исходное значение и измененное значение для поля, и я хочу сделать это с меньшим количеством возможных запросов.

Есть идеи? Спасибо.

Ответы [ 2 ]

1 голос
/ 27 марта 2012

В простом случае, когда вы хотите получить последнее изменение значения адреса для записи с идентификатором 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)
0 голосов
/ 28 марта 2012

Это можно решить с помощью чистого SQL в современных Postgres, используя WITH RECURSIVE.

Для 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';

Call:

SELECT * FROM f_get_org_val(123);

Предполагается, что все деревья имеют корневой узел с parent_id = 0.Никаких циклических ссылок, или вы получите бесконечный цикл.Возможно, вы захотите добавить счетчик и выйти из цикла после x итераций.

...