sql - 加入 2 个表并仅保留第一个最近的事件
问题描述
我有以下当前表格:
table_1
id | timestamp | origin | info
table_2
id | timestamp | origin | type
我的目标是为表 2 中的每一行找到表 1 中的原始事件。我只想保留第一个事件。例如:
table 1
1 | 1000 | "o1" | "i1"
2 | 2000 | "o2" | "i2"
3 | 2010 | "o2" | "i2"
table 2
1 | 1010 | "o1" | "t1"
2 | 2100 | "o2" | "t2"
我的预期结果是:
table_2.id | table_2.timestamp | table_2.origin | table_2.type | table_1.info | table_1.timestamp
1 | 1010 | "o1" | "t1" | "i1" | 1000
2 | 2100 | "o2" | "t2" | "i2" | 2010
目前我只是使用一个简单的连接origin
,table_2.timestamp > table_1.timestamp
它给了我:
table_2.id | table_2.timestamp | table_2.origin | table_2.type | table_1.info | table_1.timestamp
1 | 1010 | "o1" | "t1" | "i1" | 1000
2 | 2100 | "o2" | "t2" | "i2" | 2000
2 | 2100 | "o2" | "t2" | "i2" | 2010
如您所见,我不想要上面的第二行,因为我只想要 table_1 中的第一个最接近的事件。
有任何想法吗?
解决方案
一个跨数据库的解决方案是用一个相关的子查询加入和过滤:
select
t2.*,
t1.info,
t1.timestamp t1_timestamp
from
table_2 t2
inner join table_1 t1
on t1.origin = t2.origin
and t1.timestamp = (
select max(t11.timestamp)
from table_1 t11
where t11.origin = t2.origin and t11.timestamp < t2.timestamp
)
order by t2.id
由于您使用的是 Postgres,因此您可以使用方便的语法distinct on
;这实际上可能表现更好:
select
distinct on(t2.id)
t2.*,
t1.info,
t1.timestamp t1_timestamp
from
table_2 t2
inner join table_1 t1
on t1.origin = t2.origin and t1.timestamp < t2.timestamp
order by t2.id, t1.timestamp desc
DB Fiddle 上的演示- 两个查询都产生:
编号 | 时间戳 | 产地 | 类型 | 信息 | t1_timestamp -: | --------: | :----- | :--- | :--- | ------------: 1 | 1010 | o1 | t1 | i1 | 1000 2 | 2100 | o2 | t2 | i2 | 2010
推荐阅读
- sql - sql 加入时加入
- bash - 如何在 Jenkins 多行 shell 脚本中使用 bash 变量
- sql - 我们可以在oracle db的所有表中搜索一个字符串值吗
- c++ - C++ 观察者模式,“未命名类型”编译错误
- go - 函数中的动态返回类型
- vba - Worksheet.Protect 并不总是应用密码
- php - phpbench中的革命和迭代有什么区别?
- reactjs - React 和 forwardRef
- c# - 重定向到 DHL 跟踪站点时出现 IE 错误:属性 dcsMultiTrack 的值为 null 或未定义,不是函数对象
- laravel - Laravel,构建 6 级“主题-子主题”记录,如何设置 Db/Controllers/Crud 操作?