-1

我正在寻找一个 PostgreSQL 语句来连接两个数据库,但是简单的连接并不能满足我的要求。给出了两张表:一张是记录烤箱(基于温度和机器状态记录),另一张是记录产品。每个产品都被分配到一个烘箱运行,因此不应发生对一个产品行的双重分配。

烤箱

oven_id | runstart         | runend           | max_temp 
1       | 06.04.2020 19:33 | 06.04.2020 21:03 | 100        A
1       | 06.04.2020 23:28 | 07.04.2020 00:58 | 102        B
1       | 07.04.2020 10:00 | 07.04.2020 11:30 | 98         C
...

产品

oven_id | oven_run | product_ids | preprocessing    | postprocessing
1       | 11100    | [1,4,6]     | 06.04.2020 12:44 | 06.04.2020 21:29     1
1       | 11101    | [2,3,7]     | 06.04.2020 19:24 | 07.04.2020 08:12     2
1       | 11102    | [5,8,9]     | 07.04.2020 05:31 | 07.04.2020 19:05     3
...

我的第一种方法:

select * 
from oven
left join product
    on oven.runstart>product.preprocessing and oven.runend<product.postprocessing and oven.oven_id=product.oven_id

但是,在某些特定情况下(例如上面的示例),此查询未显示所需的结果,因为我得到了四行(为简单起见,在上面的示例中,行标记为 ABC 和 123):A-1,A -2、B-2 和 C-3

https://www.db-fiddle.com/f/dBSGUE1nhvAkiZuGnL2nqs/3

我正在寻找的实际内容是 1:1 分配(每个烤箱运行准确分配给一个产品,没有烤箱运行或产品使用两次),因此每个烤箱行应分配给一个产品行。鉴于上面显示的示例,从逻辑的角度来看,组合 A-2 应该被忽略,否则一个产品将在烤箱中两次(产品 2 必须运行 B,否则运行 B 中没有产品)。

知道如何调整查询以仅接收三行:A-1、B-2、C-3

谢谢你的支持!

4

1 回答 1

0

您将无法完美匹配它们,您没有必要的数据。

前任 如果您有以下设置(X 轴上的时间):

<-- preprocessing 1 ---------------------------------- postprocessing 1 -->
   <-- preprocessing 2 -------------------------------- postprocessing 2 -->
      <-- runstart A --- runend A -->
                                      <-- runstart B -- runend B -->

你不能真的配对1-A 和 2-B。如果你这样做,那只是猜测。但是,如果猜测对您来说足够好,您可以搜索烤箱产品对 1-by-1,f.ex。有了这个:

with recursive pairs(o, p) as (
  select * from (
    select oven, product
    from oven
    left join product
      on oven.oven_id = product.oven_id
      and tsrange(preprocessing, postprocessing) @> tsrange(runstart, runend)
    order by runstart
    limit 1
  ) as initial
  union all
  select * from (
    select oven, product
    from pairs, oven
    left join product
      on oven.oven_id = product.oven_id
      and tsrange(preprocessing, postprocessing) @> tsrange(runstart, runend)
    where (o) != oven -- use row-unique ID here, if you have
    and (o).runstart <= oven.runstart
    order by runstart
    limit 1
  ) as next
)
select (o).*, (p).*
from pairs

https://www.db-fiddle.com/f/3711YsHr3F5warVNaAB6LC/0

PS:这仅适用于 1 oven_id。如果您需要同时收集这些oven_id,您还需要使用一些聚合(但这会使查询过于复杂,我不确定此时是否值得付出努力。)

于 2020-04-20T13:33:43.887 回答