【问题标题】:PostgreSQL: Joining two tables by timestamp without double occurancePostgreSQL:按时间戳连接两个表而不会出现两次
【发布时间】:2020-04-20 10:09:26
【问题描述】:

我正在寻找一个 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

感谢您的支持!

【问题讨论】:

  • 我得到 3 行,其中 1 行不匹配。 db-fiddle.com/f/dBSGUE1nhvAkiZuGnL2nqs/1
  • @BjarniRagnarsson 你是对的。使用 phyton/pandas 似乎存在显示错误。我稍后会对此进行检查。现在,我为这两个表取了其他值:db-fiddle.com/f/dBSGUE1nhvAkiZuGnL2nqs/3
  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出您可以给出的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。隔离第一个错误的子表达式及其输入和输出。 (调试基础。)
  • 您没有清楚地描述结果,输出如何是输入的函数。你只是在这里和那里给出关于它应该或不应该是什么样子或有什么的片段。在给出业务关系(船舶)/关联或表(基础或查询结果)时,说明其中的一行根据其列值说明了业务情况。就运算符和表达式的工作方式而言,说出您期望得到什么以及为什么期望得到它。请不要添加“编辑”等,只需将您的帖子编辑为最佳演示文稿即可。对文本使用文本,而不是链接/图像。 How to Ask
  • 请将提问所需的所有内容放在帖子本身中,而不仅仅是摆弄。 PS 包括最小代表性输入的所需输出。 PS这仍然不清楚,仍然没有给出规范或清楚地描述您的问题。没有人可以接受这个描述并知道什么查询是可以的。 PS“逻辑观点”没有任何意义。

标签: postgresql join


【解决方案1】:

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

F.ex.如果您有以下设置(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 收集这些信息,您还需要使用一些聚合(但这会使查询过于复杂,我不确定此时是否值得付出努力。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-28
    • 2019-11-01
    • 2021-03-31
    • 1970-01-01
    • 2020-09-14
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多