在另一个 table 中查找与值最接近的匹配项
Find closest match to value in another table
我有一个 table_a,在 Postgre 中每个时间戳都有很多行和列SQL 13. 我试图找到 X 列中的值最接近基准值的行从另一个 table 获得。
第二个 table 每个时间戳只有一个基准值。对于每个时间戳,我需要 return table_a 的大部分列。当直接提供基准值时,下面的查询工作正常。
如何从 table_b 中获取基准值以用于此查询?
简单地将 table_b.benchmark 替换为 (SELECT benchmark FROM table_b WHERE table_a.timestamp = table_b.timestamp) 导致 'relation "t1" does not exist' 错误。
也找不到有效的连接。
table_a:
+-----------------+-----+---------------+
| timestamp | x | other_columns |
+-----------------+-----+---------------+
| 2020-01-01 8:00 | 100 | |
| 2020-01-01 8:00 | 200 | |
| 2020-01-01 8:00 | 300 | |
| 2020-01-01 8:00 | 400 | |
| 2020-01-01 8:00 | 500 | |
| ... | | |
| 2020-01-01 9:00 | 100 | |
| 2020-01-01 9:00 | 200 | |
| 2020-01-01 9:00 | 300 | |
| 2020-01-01 9:00 | 400 | |
| 2020-01-01 9:00 | 500 | |
| ... | | |
+-----------------+-----+---------------+
table_b:
+-----------------+-----------+
| timestamp | benchmark |
+-----------------+-----------+
| 2020-01-01 8:00 | 340 |
| 2020-01-01 9:00 | 380 |
| ... | |
+-----------------+-----------+
预期结果:
+-----------------+-----+
| timestamp | x |
+-----------------+-----+
| 2020-01-01 8:00 | 300 |
| 2020-01-01 9:00 | 400 |
| ... | |
+-----------------+-----+
SQL查询:
WITH date_filter AS (
SELECT *
FROM table_a
WHERE timestamp >= {start_date} and timestamp < {end_date}
)
SELECT DISTINCT t1.timestamp, t1.x, t1.etc
FROM date_filter AS t1
INNER JOIN (
SELECT timestamp, MIN(ABS(x - (table_b.benchmark))) AS target_value
FROM t1
GROUP BY timestamp
) AS t2
ON t2.timestamp = t1.timestamp AND t2.target_value = ABS(x - (table_b.benchmark))
ORDER BY timestamp ASC;```
我建议横向连接:
select b.*, a.x
from table_b b left join lateral
(select a.*
from table_a a
where a.timestamp = b.timestamp
order by abs(a.x - b.benchmark)
limit 1
) b
on 1=1;
一个选项使用横向连接:
select b.timestamp, a.x
from table_b b
cross join lateral (
select a.*
from table_a a
where a.timestamp = b.timestamp
order by abs(a.x - b.benchmark)
limit 1
) a
您也可以使用 distinct on
:
select distinct on (b.timestamp) b.timestamp, a.x
from table_b b
inner join table_a a on a.timestamp = b.timestamp
order by b.timestamp, abs(a.x - b.benchmark)
我有一个 table_a,在 Postgre 中每个时间戳都有很多行和列SQL 13. 我试图找到 X 列中的值最接近基准值的行从另一个 table 获得。 第二个 table 每个时间戳只有一个基准值。对于每个时间戳,我需要 return table_a 的大部分列。当直接提供基准值时,下面的查询工作正常。
如何从 table_b 中获取基准值以用于此查询?
简单地将 table_b.benchmark 替换为 (SELECT benchmark FROM table_b WHERE table_a.timestamp = table_b.timestamp) 导致 'relation "t1" does not exist' 错误。
也找不到有效的连接。
table_a:
+-----------------+-----+---------------+
| timestamp | x | other_columns |
+-----------------+-----+---------------+
| 2020-01-01 8:00 | 100 | |
| 2020-01-01 8:00 | 200 | |
| 2020-01-01 8:00 | 300 | |
| 2020-01-01 8:00 | 400 | |
| 2020-01-01 8:00 | 500 | |
| ... | | |
| 2020-01-01 9:00 | 100 | |
| 2020-01-01 9:00 | 200 | |
| 2020-01-01 9:00 | 300 | |
| 2020-01-01 9:00 | 400 | |
| 2020-01-01 9:00 | 500 | |
| ... | | |
+-----------------+-----+---------------+
table_b:
+-----------------+-----------+
| timestamp | benchmark |
+-----------------+-----------+
| 2020-01-01 8:00 | 340 |
| 2020-01-01 9:00 | 380 |
| ... | |
+-----------------+-----------+
预期结果:
+-----------------+-----+
| timestamp | x |
+-----------------+-----+
| 2020-01-01 8:00 | 300 |
| 2020-01-01 9:00 | 400 |
| ... | |
+-----------------+-----+
SQL查询:
WITH date_filter AS (
SELECT *
FROM table_a
WHERE timestamp >= {start_date} and timestamp < {end_date}
)
SELECT DISTINCT t1.timestamp, t1.x, t1.etc
FROM date_filter AS t1
INNER JOIN (
SELECT timestamp, MIN(ABS(x - (table_b.benchmark))) AS target_value
FROM t1
GROUP BY timestamp
) AS t2
ON t2.timestamp = t1.timestamp AND t2.target_value = ABS(x - (table_b.benchmark))
ORDER BY timestamp ASC;```
我建议横向连接:
select b.*, a.x
from table_b b left join lateral
(select a.*
from table_a a
where a.timestamp = b.timestamp
order by abs(a.x - b.benchmark)
limit 1
) b
on 1=1;
一个选项使用横向连接:
select b.timestamp, a.x
from table_b b
cross join lateral (
select a.*
from table_a a
where a.timestamp = b.timestamp
order by abs(a.x - b.benchmark)
limit 1
) a
您也可以使用 distinct on
:
select distinct on (b.timestamp) b.timestamp, a.x
from table_b b
inner join table_a a on a.timestamp = b.timestamp
order by b.timestamp, abs(a.x - b.benchmark)