Я не уверен, как описать мою проблему словами, поэтому я создал иллюстрацию, чтобы помочь.
|-------------------------------------------|
| 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 должна возвращать две строки (очевидно из-за вставок).
- Версия 2 должна возвращать одну строку (менее очевидно, но строка существует, пока не будет вызвана операция DELETE).
- Версия 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
... но результаты не возвращаются так, как я ожидаю (без результатов).