Выбрать строки, которые соответствуют состоянию приложения в определенный момент истории - PullRequest
0 голосов
/ 30 июня 2018

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

|-------------------------------------------|
| version_table (many-to-many)              |
|-------------------------------------------|
| version_id | a_id | b_id | operation_type |
|------------|------|------|----------------|
| 1          | 1    | 1    | INSERT         |
| 1          | 1    | 2    | INSERT         |
| 2          | 1    | 1    | DELETE         |
| 3          | 1    | 2    | DELETE         |
|------------|------|------|----------------|

В этой таблице запросы для каждой версии дадут следующие результаты:

  1. Версия 1 должна возвращать две строки (очевидно из-за вставок).
  2. Версия 2 должна возвращать одну строку (менее очевидно, но строка существует, пока не будет вызвана операция DELETE).
  3. Версия 3 должна возвращать ноль строк (все строки очищены предыдущими операциями DELETE).

Очевидно, что нам нужно извлечь все строки, которые были вставлены до или в предоставленной версии.

WHERE table.version_id <= :VERSION

Но что не очевидно, так это то, как мы исключаем строки, которые были «УДАЛЕНЫ».

AND table.version_id > alias.version_id AND alias.operation_type = "DELETE"

Это запрос, который я написал в итоге:

SELECT tag.id AS tag_id, tag.name AS tag_name 
FROM tag
JOIN article_tag_version ON article_tag_version.tag_id = tag.id
LEFT OUTER JOIN article_tag_version AS article_tag_version_1 ON
    article_tag_version_1.tag_id = tag.id AND
    article_tag_version_1.operation_type = "DELETE"
WHERE article_tag_version.version_id <= ? AND article_tag_version.version_id > article_tag_version_1.version_id

... но результаты не возвращаются так, как я ожидаю (без результатов).

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Я бы просто выбрал самую последнюю запись для каждой пары a_id / b_id, а затем отфильтровал те, которые были удалены:

select atv.*
from (select distinct on (a_id, b_id) atv.*
      from article_tag_version atv
      where version <= ?  -- the version you care about
      order by a_id, b_id, version desc
     ) atv
where operation_type <> 'DELETE';
0 голосов
/ 30 июня 2018

Вы можете проверить с помощью NOT EXISTS, была ли «вещь» (что бы она ни была) удалена в версии между версией, в которую она была вставлена, и целевой версией.

SELECT *
       FROM version_table v1
       WHERE v1.operation_type = 'INSERT'
             AND NOT EXISTS (SELECT *
                                    FROM version_table v2
                                    WHERE v2.version_id >= v1.version_id
                                          AND v2.version_id <= :VERSION
                                          AND (v2.a_id,
                                               v2.b_id) = (v1.a_id,
                                                           v1.b_id)
                                          AND v2.operation_type = 'DELETE')
             AND v1.version_id <= :VERSION;

SQL Fiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...