【问题标题】:ORACLE SQL - multiple JOINs from same tableORACLE SQL - 来自同一个表的多个 JOIN
【发布时间】:2022-01-18 14:46:06
【问题描述】:

我在一个表中有与物料交易相关的数据,与物料相关的日志历史标题数据在另一个表中,详细的日志历史数据在第三个表中。我正在尝试获取与材料表匹配的不同状态更新日期,但我得到一个材料交易的重复行

原物料交易表:

ORDER_NO MATERIAL QTY
0001 MAT01 2
0002 MAT02   5

Original Log History Header 事务表:

ORDER_NO LOG_ID
0001 1001
0001 1002

状态代码 1 表示已打开,代码 2 表示已关闭

详细的日志历史表:

LOG_ID STATUS_CODE DATE
1001 1 11/12/2021
1002 2   15/12/2021

使用以下 SQL 查询:

SELECT 
       TO_CHAR (m.order_no) order_no,
       m.material,
       a.date opened_date,
       ab.closed_date
  FROM MATERIAL_TRANSACTIONS m
       INNER JOIN HISTORY_LOG t
          ON m.ORDER_NO = t.ORDER_NO
       INNER JOIN HISTORY_LOG_DETAILED a
          ON     t.LOG_ID = a.LOG_ID
             AND a.STATUS_CODE = '1'
       INNER JOIN HISTORY_LOG_DETAILED ab
          ON     t.LOG_ID = ab.LOG_ID
             AND ab.STATUS_CODE = '2'

我得到以下结果:

ORDER_NO MATERIAL QTY OPENED_DATE CLOSED_DATE
0001 MAT01 2 11/12/2021
0001 MAT01   2 15/12/2021

我想将状态日期与下面的同一行:

ORDER_NO MATERIAL QTY OPENED_DATE CLOSED_DATE
0001 MAT01 2 11/12/2021 15/12/2021

如果已经有类似问题的主题,我将不胜感激,并且非常抱歉。

【问题讨论】:

    标签: sql oracle join oracle11g


    【解决方案1】:

    您的问题出现是因为您加入了历史记录表,该表包含 2 条订单记录。如果您使用 2 个内联表且恰好包含 1 条记录,则可以将其展平。

    with opened_dates as (
      select h.order_id, d.date
      from history h
      inner join details d on h.log_id = d.log_id and d.status_code = '1'
    ), closed_dates as (
      select h.order_id, d.date
      from history h
      inner join details d on h.log_id = d.log_id and d.status_code = '2'
    )
    select to_char (m.order_no) order_no,
           m.material,
           o.date opened_date,
           c.date closed_date
    from material_transactions m
    join opened_dates o on m.order_no = o.order_no
    join closed_dates c on m.order_no = c.order_no
    ;
    

    【讨论】:

    • 太棒了!这成功了,查询执行相当快。感谢马丁的帮助!
    【解决方案2】:

    只是一个想法:

    我加入了HISTORY_LOGHISTORY_LOG_DETAILED表来获取特定状态的日期,并设置为OPENED_DATECLOSED_DATE(如果状态1,则打开日期为DATE列,否则设置为@987654326 @)

    然后按ORDER_NO 对这些记录进行分组,并最大化日期值以获得实际的OPENED_DATECLOSED_DATE

    最后用MATERIAL_TRANSACTIONS 表加入这个子查询:

    SELECT 
           TO_CHAR (M.ORDER_NO) ORDER_NO,
           M.MATERIAL,
           QTY,
           L_T.OPENED_DATE,
           L_T.CLOSED_DATE
      FROM MATERIAL_TRANSACTIONS M  
      INNER JOIN 
      (
      SELECT  L.ORDER_NO , 
     MAX( CASE WHEN LD.STATUS_CODE = 1 THEN LD.DATE ELSE TO_DATE('01.01.0001','dd.mm.yyyy')  END ) OPENED_DATE
    MAX( CASE WHEN LD.STATUS_CODE = 2 THEN LD.DATE ELSE TO_DATE('01.01.0001','dd.mm.yyyy')  END ) CLOSED_DATE 
       FROM 
      HISTORY_LOG L 
      INNER JOIN HISTORY_LOG_DETAILED LD ON LD.LOG_ID = L.LOG_ID
     GROUP BY L.ORDER_NO
     ) L_T on L_T.ORDER_NO = M.ORDER_NO
    

    注意:我没有测试它。所以可能会有小的语法错误。请检查它并为更好的帮助添加一个小提琴,以便我可以测试我的查询

    【讨论】:

    • 感谢阿里!您的建议确实有效,但执行查询需要相当长的时间,所以我最终改用了 Martin 的建议
    • 谢谢伙计。我很高兴它有所帮助。顺便说一句,它很慢,因为我忘记将子查询与表连接起来:)))))我现在会更新它
    猜你喜欢
    • 2012-03-11
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 2017-02-20
    • 2020-09-15
    • 2011-10-20
    相关资源
    最近更新 更多