首页 > 解决方案 > 如何将一个表与另一个表中的一系列值连接起来?

问题描述

我目前非常希望将两张桌子连接在一起。但通常,当您想要连接两个表时,它们只有在两边的值本身相等时才会连接。如果一个值在一个区间内,我正在寻找一个连接。让我解释:

我有这些表:

inscription(studentNumber, note)
thresVal(threshold, value)

表题字看起来有点像这样:

studentNumber | note 
--------------+------
123           | 78   
456           | 65   
789           | 52   
012           | 90   
345           | 37   

tresVal看起来像这样:

 treshold | value
----------+--------
       90 |    4.3
       85 |      4
       80 |    3.7
       77 |    3.3
       73 |      3
       70 |    2.7
       65 |    2.3
       60 |      2
       57 |    1.7
       54 |    1.3
       50 |      1 
       35 |    0.5
        0 |      0

现在,我想要的是一个连接,检查学生的笔记在什么范围内,并相应地添加行“值”,如下所示:

studentNumber | note | value
--------------+-------
123           | 78   | 3.3
456           | 65   | 2.3
789           | 52   | 1
012           | 90   | 4.3
345           | 37   | 0.5

如您所见,范围介于行的值与其前任值之间。65 的音符大于或等于阈值 65,因此它的值必须是 2.3。从 65 到 69 的所有音符必须被赋予 2.3 的值,依此类推。

我似乎无法为这个问题想出一些好的东西,我所能想到的就是一个接一个地对每一种可能性进行硬编码,但必须有一个更简单的答案。

标签: postgresqljoinrange

解决方案


“通常......只有当双方的价值观本身相等时才加入” - 那又怎样!这是早期努力导致这种情况的结果,而不是因为自然是那样的。并且没有什么需要通常的方式。它不适合您的情况,然后根据需要设置加入。在这种情况下,您需要加入一系列值 - 这样做。
以下将为您提供。CTE 使用窗口 LEAD 函数从当前行的下一行组合值并创建一个开放、封闭的范围。然后将这个范围加入到结果范围上的铭文中。

with tresVal_range as 
     (select int4range(treshold, coalesce(lead(tresHold) over(order by treshold), 10000),'[)') treshold, value
        from tresVal
     )
select i.studentnumber,i.note, t.value
  from inscription   i
  join tresval_range t
    on i.note <@ t.treshold
 order by i.studentnumber;    

推荐阅读