SQL получить записи, имеющие последнюю ассоциацию, соответствующую указанному значению c - PullRequest
1 голос
/ 27 мая 2020

Контекст

Используя PostgreSQL, я сохраняю articles и связанные с ними events. Вот простая структура двух таблиц для примера:

Таблица статей

+----+-----------+-----------------------+
| ID |   title   |      description      |
+----+-----------+-----------------------+
|  1 | article 1 | article 1 description |
|  2 | article 2 | article 2 description |
|  3 | article 3 | article 3 description |
|  4 | article 4 | article 4 description |
|  5 | article 5 | article 5 description |
+----+-----------+-----------------------+

Таблица событий

+-----+-----------+--------------+----------------+--------------+
| ID  |   name    | eventable_id | eventable_type | created_at   |
+-----+-----------+--------------+----------------+--------------+
|  1  | validated |            1 | Article        | 2020-05-10   |
|  2  | reported  |            1 | Article        | 2020-05-11   |
|  3  | reported  |            2 | Article        | 2020-05-10   |
|  4  | reported  |            2 | Article        | 2020-05-11   |
|  5  | reported  |            2 | Article        | 2020-05-12   |
|  6  | reported  |            3 | Article        | 2020-05-20   |
|  7  | validated |            3 | Article        | 2020-05-21   |
|  8  | reported  |            4 | Article        | 2020-05-12   |
|  9  | moved     |            4 | Article        | 2020-05-13   |
|  10 | reported  |            4 | Article        | 2020-05-14   |
|  11 | moved     |            5 | Article        | 2020-05-13   |
|  12 | moved     |            5 | Article        | 2020-05-14   |
+-----+-----------+--------------+----------------+--------------+

Проблема

Здесь мне нужно иметь возможность получить все articles, последние events которых reported.

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

  • article 1: потому что это было validated, затем reported
  • article 2: потому что это было только reported
  • article 4: потому что это было moved, то reported (то же, что и статья 1)

Как видите:

  • article 3: не должно возвращаться, потому что его последнее событие - validated.
  • article 5: не должно возвращаться, потому что его последнее событие - moved.

Я могу легко найти все articles, имеющие событие reported. Но как сделать так, чтобы последнее событие было reported?

Вот что я пытался сделать до сих пор безуспешно:

SELECT *
FROM articles a
INNER JOIN (
    SELECT *
    FROM events
    WHERE name = 'reported'
    ORDER BY created_at
    LIMIT 1
) AS e ON e.moderable_id = a.id AND e.moderable_type = 'Article'

Сейчас у нас есть:

  • 459 892 articles
  • 62074 events

1 Ответ

1 голос
/ 27 мая 2020

Вы можете использовать коррелированный подзапрос для фильтрации:

select a.*
from articles a
where 
    (
        select e.name
        from events e
        where e.eventable_id = a.id and e.eventable_type = 'Article'
        order by created_at desc 
        limit 1
    ) = 'reported'

Мы могли бы также express это с боковым соединением:

select a.*
from articles a
inner join lateral (
    select e.name 
    from events 
    where e.eventable_id = a.id and e.eventable_type = 'Article'
    order by created_at desc 
    limit 1
)  x on x.status = 'reported'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...