【问题标题】:Postgresql: find closest matching pairs in two arraysPostgresql:在两个数组中查找最接近的匹配对
【发布时间】:2020-01-30 14:44:29
【问题描述】:

我在 Postgresql 中有两个表:

a:

name | power
:--- | :----
a1   | 12   
a2   | 6    
a3   | 3    
a4   | 1 

b

name | power
:--- | :----
b1   | 11   
b2   | 4  

我想有效地(我需要以 10Hz 执行此查询)找到最接近的匹配功率,即结果应该是

name | power | name | power
:--- | :---- | :--- | :----
a1   | 12    | b1   | 11   
a3   | 3     | b2   | 4 

我已经使用循环实现了它,但是,如果有更有效的方法来找到解决方案,我会很高兴。

非常感谢

【问题讨论】:

  • 请描述您的“阵列”。这些是元组数组吗?二维数组?具有多个二元素数组的列?表结构会有所帮助。
  • 两个表都很简单(b和a结构一样):CREATE TABLE a ( name text, power real );
  • 一个 b 值是否可以匹配两个 a 值(例如,如果有一对 (a5, 10),则 (b1, 11) 对将同时匹配)
  • 是的,可以这样。然后,以下解决方案之一就可以了:只映射一个,或同时映射两者。

标签: arrays postgresql loops sorting find


【解决方案1】:

demo:db<>fiddle

SELECT DISTINCT ON (b.name)
    a.*,
    b.*
FROM a CROSS JOIN b
ORDER BY b.name, abs(a.power - b.power)
  1. CROSS JOIN 所有记录能够将所有 a 值与所有 b 值进行比较
  2. 计算这些对之间的绝对差以找到最小值
  3. DISTINCT ON (b.name) 给出包含某个b.name 值的第一条记录(因为它是按差异排序的,所以它将与a 值的差异最小的记录)

【讨论】:

  • @Jens 如果一个答案解决了您的问题,请不要忘记接受(用于关闭问题)(点击相关答案左上角的复选标记)
【解决方案2】:

@S-Man 的解决方案可能是最好的解决方案,但在某些情况下使用横向连接可能更快:

SELECT sub.*, b.*
FROM b
JOIN LATERAL 
  (select a.* FROM a ORDER BY abs(a.power-b.power) LIMIT 1) sub 
ON TRUE;

如果你想返回所有的 a,并且 b 出现多次,只需翻转这个:

SELECT a.*, sub.*
FROM a
JOIN LATERAL 
  (select b.* FROM b ORDER BY abs(a.power-b.power) LIMIT 1) sub 
ON TRUE;

【讨论】:

  • 为这个想法点赞! :) 您可以将 JOIN LATERAL ... ON TRUE 更改为 CROSS JOIN LATERAL
猜你喜欢
  • 2019-11-02
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多