我有两张桌子:
表1
id date_measured value 1
1 01/01/2017 5
1 02/20/2017 6
1 04/01/2017 5
2 03/02/2017 5
2 04/02/2017 3
表2
id date_measured value 2
1 01/06/2017 5
1 03/01/2017 6
2 02/01/2017 5
2 03/09/2017 7
2 04/05/2017 4
我想加入它,以便每个id匹配,最接近的日期匹配:
id date_measured1 value 1 date_measured2 value 2
1 01/01/2017 5 01/06/2017 5
1 02/20/2017 6 03/01/2017 6
2 02/01/2017 5 02/01/2017 5
2 03/02/2017 5 03/09/2017 7
2 04/02/2017 3 04/05/2017 4
等。每个测量日期的每个id的IE采用另一个表中最接近的测量日期并使其成行。
接近的东西 SELECT *
FROM table1 a
INNER JOIN table2 b
ON a.id = b.id
AND <date from a is closest date from b>
但我不知道如何做第二部分。有什么建议吗?
答案 0 :(得分:2)
在标准SQL中,您可以使用相关子查询获取日期:
select t1.*,
(select t2.date_measured
from table2 t2
where t2.id = t1.id
order by abs(t2.date_measured - t1.date_measured) asc
fetch first 1 row only
) as t2_date_measured
from table1 t1;
然后,您可以加入table2
以获取该行的其他信息。
以上是通用SQL(不一定是标准SQL)。日期/时间函数往往是每个数据库特有的;所以-
可能不适用于差异。并非所有数据库都支持fetch first 1 row only
,但几乎所有数据库都支持执行相同操作的某种机制。
答案 1 :(得分:0)
如果您有窗口功能,请使用ROW_NUMBER()
:
SQL DEMO我使用postgresql,因此日期函数可能因rdbms而异。
WITH cte as (
SELECT *,
t1.id as t1_id,
t1.date_measured as t1_date,
t1.value1,
t2.id as t2_id,
t2.date_measured as t2_date,
t2.value2,
date_part('day', age(t1.date_measured, t2.date_measured)) as days,
ROW_NUMBER() OVER (PARTITION BY t1.id, t1.date_measured
ORDER BY abs(date_part('day', age(t1.date_measured, t2.date_measured)))
) as rn
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.id
)
SELECT *
FROM cte
WHERE rn = 1
ORDER BY t1_id, t1_date