SQL 获取具有与特定值匹配的最新关联的记录
SQL get records having latest association matching a specific value
上下文
使用 PostgreSQL,我正在存储 articles
及其关联的 events
。为了示例,这里是 2 table 的简单结构:
文章table
+----+-----------+-----------------------+
| 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 |
+----+-----------+-----------------------+
事件table
+-----+-----------+--------------+----------------+--------------+
| 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
: 不应该是 return 因为它的最新事件是 validated
.
article 5
: 不应该是 return 因为它的最新事件是 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
您可以使用相关子查询进行过滤:
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'
我们也可以用横向连接来表达:
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'
上下文
使用 PostgreSQL,我正在存储 articles
及其关联的 events
。为了示例,这里是 2 table 的简单结构:
文章table
+----+-----------+-----------------------+
| 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 |
+----+-----------+-----------------------+
事件table
+-----+-----------+--------------+----------------+--------------+
| 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
: 不应该是 return 因为它的最新事件是validated
.article 5
: 不应该是 return 因为它的最新事件是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
您可以使用相关子查询进行过滤:
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'
我们也可以用横向连接来表达:
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'