【问题标题】:Search data based on timestamp with multiple joins and dependency between timestamp in Postgres基于具有多个连接的时间戳和 Postgres 中时间戳之间的依赖关系搜索数据
【发布时间】:2020-09-23 20:39:56
【问题描述】:

我有两张表prod_replay_inprod_replay_out,如下所示。

对于msg_type 作为prod_replay_in 表中的CDST010,它在prod_replay_out 表中作为CDST01C 得到确认。与msg_type 相同,因为 CDST100 在prod_replay_out 表中的确认消息为CDST10C。在下表中,cdsx_time 很重要。例如,第二条 CDST100 消息将具有基于 cdsx_time 的第二条 CDST10C 消息。

注意: 2 个表之间的 JOIN 是基于 cdsx_id,因为它在两个表之间是通用的。 CDST010 和CDST01Cprod_replay_inprod_replay_out 表中将只有一个相同cdsx_id 的条目。此外,CDST100 和CDST10C 消息的数量因cdsx_id 而异。

我要搜索什么?

我想根据以下条件在prod_replay_in 表中搜索 CDST100 消息的数量:

  • 如果 CDST100 的bancs_msg 中的第四个字符与 CDST01C 的msg_body 中的第四个字符匹配,则获取第一个 CDST100
  • 如果 CDST100 的 bancs_msg 中的第四个字符与第四个字符匹配,则获取第二个 CDST100 第一个 CDST10C 的 msg_body 中的字符
  • 如果 CDST100 的 bancs_msg 中的第四个字符与第四个字符匹配,则获取第三个 CDST100 在msg_body 中用于第二个 CDST10C

上述模式就像用第一个 CDST10C 检查第二个 CDST100,用第二个 CDST10C 检查第三个 CDST100,等等。

prod_replay_in

id(serial) | msg_type(varchar) | cdsx_time(timestamp)  | cdsx_id(varchar)    | bancs_msg(text)
------------------------------------------------------------------------------------------
8334698    | CDST010           | 2020-02-24 14:23:01.0 | T202005518525        | ABCD
8341809    | CDST100           | 2020-02-24 14:47:38.0 | T202005518525        | ANOC
8342732    | CDST100           | 2020-02-24 14:51:53.0 | T202005518525        | PHLM
8344890    | CDST100           | 2020-02-24 15:15:14.0 | T202005518525        | JKQO

prod_replay_out

    id(serial) | msg_type(varchar) | cdsx_time(timestamp)    | cdsx_id(varchar)     | msg_body(text)
    ------------------------------------------------------------------------------------------
    42164527   | CDST01C           | 2020-02-24 14:23:08.016 | T202005518525        | AQRS
    42176068   | CDST10C           | 2020-02-24 14:47:47.056 | T202005518525        | STUM
    42177522   | CDST10C           | 2020-02-24 14:52:00.031 | T202005518525        | XYZK
    42245814   | CDST10C           | 2020-02-24 15:30:00.045 | T202005518525        | ASQO

我尝试了什么?

我已尝试创建用于匹配第一个 CDST100 和 CDST01C 的 sql 查询,但不确定如何将后续 CDST100 与 CDST10C 进行比较?

SELECT count(T.id) FROM prod_replay_in T JOIN prod_replay_out O ON T.CDSX_ID = O.CDSX_ID
  JOIN prod_replay_out K ON K.CDSX_ID = O.CDSX_ID
  WHERE T.MSG_TYPE = 'CDST100'
  and O.msg_type = 'CDST01C'
  and K.msg_type = 'CDST10C'
  and ( (
        min(T.cdsx_time) > O.cdsx_time
        and substr(T.bancs_msg,4,1) = substr(O.msg_body,4,1)
        )
      );

【问题讨论】:

  • 是否保证每条prod_replay_in 记录在您的数据中都有对应的prod_replay_out 记录?
  • @MikeOrganek 是的,cdsx_id 将用于两个表。如果没有,我不会考虑将它用于我的搜索查询,因为我在 sql 中使用了 JOIN。

标签: sql postgresql join sql-timestamp


【解决方案1】:

我尝试了以下代码。据我所知,它应该可以工作。如果缺少任何场景,请随时提出建议。

Select count(T.*) from PROD_REPLAY_IN T, PROD_REPLAY_OUT O
Where T.msg_type = 'CDST100'
AND O.msg_type IN ('CDST01C', 'CDST10C')
AND T.cdsx_id = O.cdsx_id
AND substr(T.bancs_msg,4,1) = substr(O.msg_body,4,1)
AND (O.cdsx_id, O.cdsx_time) IN (Select Y.cdsx_id, Max(Y.cdsx_time) from PROD_REPLAY_OUT Y
        Where Y.msg_type IN ('CDST01C', 'CDST10C')
        AND O.cdsx_id = Y.cdsx_id
        AND T.cdsx_time > Y.cdsx_time
        GROUP BY Y.cdsx_id
        )

【讨论】:

    【解决方案2】:

    只要您知道每个prod_replay_in 行都会有一个对应的prod_replay_out 行(按时间戳记),您就可以将其设置为使用窗口函数在重播开始时回避不同的消息类型:

    with interleave as (
      select msg_type, cdsx_time, cdsx_id, bancs_msg as msg, 'in' as direction
        from prod_replay_in
      union all
      select msg_type, cdsx_time, cdsx_id, msg_body as msg, 'out' as direction
        from prod_replay_out
    ), match_cdst100 as (
      select cdsx_id, msg,
             lag(msg) over (partition by cdsx_id
                                order by cdsx_time) as last_msg
        from interleave
       where msg_type = 'CDST100'
    )
    select cdsx_id, count(*) 
      from match_cdst100
     where substr(msg, 4, 1) = substr(last_msg, 4, 1)
     group by cdsx_id;      
              
    

    【讨论】:

    • 显示错误为Error: ERROR: column "match_cdst100.cdsx_id" must appear in the GROUP BY clause or be used in an aggregate function Position: 442 SQLState: 42803 ErrorCode: 0
    • @JayParmar 我更新了答案以包含group by
    猜你喜欢
    • 1970-01-01
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    相关资源
    最近更新 更多