SQL 获取具有与特定值匹配的最新关联的记录
Posted
技术标签:
【中文标题】SQL 获取具有与特定值匹配的最新关联的记录【英文标题】:SQL get records having latest association matching a specific value 【发布时间】:2020-09-13 23:56:33 【问题描述】:上下文
使用 PostgreSQL,我正在存储 articles
及其关联的 events
。为了示例,以下是 2 个表的简单结构:
文章表
+----+-----------+-----------------------+
| 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 892articles
62 074 events
【问题讨论】:
你试过查询了吗? 注意:你的事件似乎比文章少? @wildplasser 是的,因为并非所有文章都有事件 【参考方案1】:您可以使用相关子查询进行过滤:
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'
【讨论】:
非常感谢,您的两个示例实际上都在工作(我需要使用更大的数据运行更多测试以确保这一点)。我有一个问题:这些查询中哪个最快?我们目前有 459 891articles
和 62 074 events
@lkartono:我认为有相当多的等价物(并且可能,它们产生相同的执行计划)。不过,您可能希望根据您的数据评估性能。 events(eventable_id, eventable_type, created_at, name)
上的索引可能会有所帮助。
感谢有关索引的提示,从 21 秒缩短到 118 毫秒 :)以上是关于SQL 获取具有与特定值匹配的最新关联的记录的主要内容,如果未能解决你的问题,请参考以下文章