【问题标题】:Returning relevant date from multiple tables including additional table info从多个表中返回相关日期,包括附加表信息
【发布时间】:2012-01-26 18:26:06
【问题描述】:

这是从之前通过 stackoverflow (Returning nearest date to date in a different table) 解决的查询继续进行的,但是,我现在希望进一步开发它。

我的 SQL 是这样的:

SELECT *
FROM (SELECT O_ASSESSMENTS.ASM_SUBJECT_ID as "P Number", 
             O_ASSESSMENTS.ASM_ID as "Assessment ID", 
             O_ASSESSMENTS.ASM_START_DATE as "Assessment Start",  
             O_ASSESSMENTS.ASM_END_DATE as "Assessment End", 
             O_SERVICE_EVENTS.SEV_ID as "Event ID", 
             O_SERVICE_EVENTS.SEV_ACTUAL_DATE as "Event Start", 
             O_SERVICE_EVENTS.SEV_OUTCOME_DATE as "Event End",
             ROUND(O_ASSESSMENTS.ASM_START_DATE -O_SERVICE_EVENTS.SEV_ACTUAL_DATE,0) as "Likely",
             row_number() over(PARTITION BY  O_ASSESSMENTS.ASM_ID                                    
                               ORDER BY abs(O_ASSESSMENTS.ASM_START_DATE -  O_SERVICE_EVENTS.SEV_ACTUAL_DATE))as "Row Number"            
      FROM O_ASSESSMENTS 
      JOIN O_SERVICE_EVENTS
        ON O_ASSESSMENTS.ASM_SUBJECT_ID = O_SERVICE_EVENTS.SEV_SUBJECT_ID
      Where O_SERVICE_EVENTS.SEV_CODE IN ('ICS_E3','CPINVEST') AND 
            O_ASSESSMENTS.ASM_QSA_ID  IN ('AA1329','AA521') )
WHERE "Row Number" = 1

基本上,我们有两个表 - o_assessments 和 o_service_events,此 SQL 将最近的服务事件返回给评估。现在我想在查询中包含更多上下文信息,以使其对最终用户更有帮助 - 即团队名称和工作人员名称。

不幸的是,team 和 worker 再次位于不同的表中(o_responsibility),并通过 asm_id 到 res_rec_id 链接到 o_assessments。

问题是,我真的不知道如何将此表调用到上面的 sql 中 - 所以任何建议都将不胜感激!

我还想知道是否可以调整现有查询以仅在“可能”字段的差异为 0 时返回相应的事件(因为更大的可能与该特定评估无关)。我知道我可以将它添加到 where,但是如果我添加行

and "Likely" = 0

它只返回带有事件的评估,不会突出任何问题(即没有相应事件的评估)。

我一直在学习 SQL,但目前有很多东西似乎真的超出了我的能力范围,因此非常感谢任何建议!我不确定是修改我原来的查询还是开始一个新的查询,所以我希望我没有无意中违反任何规则。

编辑:

好的,按照马克的解决方案,这就是我的工作。

SELECT 
* 
FROM 
(SELECT 
OAS.ASM_SUBJECT_ID as "P Number",
OAS.ASM_ID as "Assessment ID",
OAS.ASM_START_DATE as "Assessment Start", 
OAS.ASM_END_DATE as "Assessment End",
OAS.ASM_AUTH_DATETIME as "Authorisation Date",
nvl(olm_bo.get_ref_desc(OAS.ASM_OUTCOME,'ASM_OUTCOME'),'') as "Outcome",
nvl(olm_bo.get_org_name(ORE.RES_PARTY_OUN_ID),'') as "Team",
nvl(olm_bo.get_per_name(ORE.RES_PARTY_ID),'') as "Worker",
OSE.SEV_ID as "Event ID",
OSE.SEV_ACTUAL_DATE as "Event Start",
OSE.SEV_OUTCOME_DATE as "Event End",
ROUND(OAS.ASM_START_DATE -OSE.SEV_ACTUAL_DATE,0) as "Likely",
row_number() over(PARTITION BY  OAS.ASM_ID                   
ORDER BY 
abs(OAS.ASM_START_DATE -  OSE.SEV_ACTUAL_DATE))as "Row Number"
FROM O_ASSESSMENTS OAS      
INNER JOIN O_RESPONSIBILITIES ORE ON OAS.ASM_ID = ORE.RES_REC_ID
AND ORE.RES_PARTY_OUN_ID = 'TEAM'
LEFT JOIN O_SERVICE_EVENTS OSE ON OAS.ASM_SUBJECT_ID = OSE.SEV_SUBJECT_ID 
AND            
OSE.SEV_CODE IN ('EVENT') 
AND             
ROUND(OAS.ASM_START_DATE - OSE.SEV_ACTUAL_DATE,0) >= -7
AND
ROUND(OAS.ASM_START_DATE - OSE.SEV_ACTUAL_DATE,0) <= 7
Where OAS.ASM_QSA_ID  IN ('ACODE')
AND
nvl(olm_bo.get_ref_desc(OAS.ASM_OUTCOME,'ASM_OUTCOME'),'') <> 'Abandon' ) WHERE "Row Number" = 1 

【问题讨论】:

  • 内部选择是否缺少某些内容?特别是在连接周围......它有一个“AND”后跟一个“WHERE”,这应该会导致语法错误
  • 抱歉,正在修改代码并复制了错误的副本...现在已修复!

标签: sql oracle date join


【解决方案1】:

试试:

SELECT *
FROM (SELECT OAS.ASM_SUBJECT_ID as "P Number", 
             OAS.ASM_ID as "Assessment ID", 
             OAS.ASM_START_DATE as "Assessment Start",  
             OAS.ASM_END_DATE as "Assessment End", 
             ORE.TEAM,
             ORE.WORKER,
             OSE.SEV_ID as "Event ID", 
             OSE.SEV_ACTUAL_DATE as "Event Start", 
             OSE.SEV_OUTCOME_DATE as "Event End",
             ROUND(OAS.ASM_START_DATE -OSE.SEV_ACTUAL_DATE,0) as "Likely",
             row_number() over(PARTITION BY  OAS.ASM_ID                                    
                               ORDER BY abs(OAS.ASM_START_DATE -  OSE.SEV_ACTUAL_DATE))as "Row Number"            
      FROM O_ASSESSMENTS OAS
      LEFT JOIN O_RESPONSIBILITIES ORE
        ON OAS.ASM_ID = ORE.RES_REC_ID
      LEFT JOIN O_SERVICE_EVENTS OSE
        ON OAS.ASM_SUBJECT_ID = OSE.SEV_SUBJECT_ID AND
           OSE.SEV_CODE IN ('ICS_E3','CPINVEST') AND 
           ROUND(OAS.ASM_START_DATE - OSE.SEV_ACTUAL_DATE,0) = 0
      Where OAS.ASM_QSA_ID  IN ('AA1329','AA521') )
WHERE "Row Number" = 1

请注意,这假定 RES_REC_ID 是 O_RESPONSIBILITIES 上的唯一标识符。

【讨论】:

  • 谢谢马克,这似乎工作得很好。对延迟反馈表示歉意。
【解决方案2】:

重新开始是正确的做法;编辑问题以“添加范围”不是一个好习惯。这属于“增加范围”,所以一个新问题是正确的方法。

SELECT
ID, "Assessment ID", 
"Assessment Start", "Assessment End", "Event ID", 
"Event Start", "Event End", Likely, Team_name, Worker_name
FROM
  (SELECT 
  O_ASSESSMENTS.ASM_SUBJECT_ID as "ID", 
  O_ASSESSMENTS.ASM_ID as "Assessment ID", 
  O_ASSESSMENTS.ASM_START_DATE as "Assessment Start",  
  O_ASSESSMENTS.ASM_END_DATE as "Assessment End", 
  O_SERVICE_EVENTS.SEV_ID as "Event ID", 
  O_SERVICE_EVENTS.SEV_ACTUAL_DATE as "Event Start", 
  O_SERVICE_EVENTS.SEV_OUTCOME_DATE as "Event End",
  ROUND(O_ASSESSMENTS.ASM_START_DATE -O_SERVICE_EVENTS.SEV_ACTUAL_DATE,0) as "Likely",
  row_number() over(PARTITION BY  O_ASSESSMENTS.ASM_ID                                    
    ORDER BY abs(O_ASSESSMENTS.ASM_START_DATE -  
    O_SERVICE_EVENTS.SEV_ACTUAL_DATE))    as "Row    Number",
  RES.TEAM_NAME,
  RES.WORKER_NAME
  FROM O_ASSESSMENTS 
  INNER JOIN  O_SERVICE_EVENTS
    ON O_ASSESSMENTS.ASM_SUBJECT_ID = O_SERVICE_EVENTS.SEV_SUBJECT_ID
  INNER JOIN O_Responsibilities res 
    ON O_Assessments.ASM_ID = res.res_rec_ID
  WHERE O_SERVICE_EVENTS.SEV_CODE IN ('ICS_E3','CPINVEST')
    AND O_ASSESSMENTS.ASM_QSA_ID IN ('AA1329','AA521') )  InnerTable
WHERE "Row Number" = 1 and (Likely = 0 or LIKELY is null)

我在这里所做的只是

  1. 在内部选择语句中添加您的加入条件
  2. 包括您要求的列,但未提供名称,因此我在 INNER 和 OUTER 选择语句中假定为 TEAM_NAME 和 WORKER_NAME
  3. 在评论原始帖子的 where 之前删除了 join 之后的 AND
  4. 为内部选择中的表名添加了别名,以防需要连接 在某个时候到外面的桌子。
  5. 将(可能 = 0 或可能为 null)添加到外部 where 子句
  6. 重新格式化 SQL 以保持此处的可读性。

以上 5 条,可能不太正确,我不完全理解您对没有服务日期的评估的评论。如果是这种情况,如果您想要所有评估和相关服务(如果存在),评估和服务之间的联接必须是左联接,而不是内部联接。目前,您只获得那些具有相关服务的评估。如果您需要所有评估,则可能需要进行其他更改。

所以...

  FROM O_ASSESSMENTS 
  INNER JOIN  O_SERVICE_EVENTS
    ON O_ASSESSMENTS.ASM_SUBJECT_ID = O_SERVICE_EVENTS.SEV_SUBJECT_ID

会变成(只有 INNER 到 LEFT 被改变了)

  FROM O_ASSESSMENTS 
  LEFT JOIN  O_SERVICE_EVENTS
    ON O_ASSESSMENTS.ASM_SUBJECT_ID = O_SERVICE_EVENTS.SEV_SUBJECT_ID

它假设评估总是有责任记录,如果没有,那里也需要左加入。

最后,需要考虑当 SEV_Actual_Date 为空时,您可能会得到什么结果。应该有什么价值?

【讨论】:

  • 谢谢你,不幸的是今年刚刚结束,所以可能没有机会在 1 月之前测试它,但一定会看看 - 特别感谢你解释你做了什么,因为这个是我需要的那种帮助!
  • @xQbert - 这不会返回可能既不是 0 也不是 null 的评估。
  • 我遗漏了一些东西......(Likely=0 或 Likely 为空)应该这样做。但是,INNER 连接当前阻止了 NULL 值,我在回复中指出了这一点;因为我没有完全理解 OP 的要求。
  • 按行号选择的要点是 OP 希望按最接近的日期排名第一的服务事件 - 可能有多个事件具有匹配的主题 ID,但只有一个日期匹配的事件是可能是事件与评估的真正匹配。 (Likely=0 或 Likely 为空)将返回具有同一天服务事件的评估 (Likely=0) 或按主题返回没有任何匹配服​​务事件的评估(Likely 为空,当离开加入服务事件时)。如果第一个匹配事件不在同一天,则它不会返回 OP 想要突出显示的评估。
  • 感谢您的回复,MB 说我想返回最可能对应事件的评估是正确的,但并非所有评估都必须有一个。
【解决方案3】:

您可以将o_responsibilities 加入到相应 ID 的内联视图中,然后将其列包含在查询中。

请注意,您需要将where likely = 0 位放在外部查询中(使用行号标准),而不是内联视图,因为likely 是一个别名。如果您想突出显示没有事件的评估,那么您应该执行 left join 并添加条件 sev_id is null

这样的事情应该可以解决问题:

select  *
from   (select    o_assessments.asm_subject_id                      as "P Number", 
                  o_assessments.asm_id                              as "Assessment ID", 
                  o_assessments.asm_start_date                      as "Assessment Start",  
                  o_assessments.asm_end_date                        as "Assessment End", 
                  o_service_events.sev_id                           as "Event Id", 
                  o_service_events.sev_actual_date                  as "Event Start", 
                  o_service_events.sev_outcome_date                 as "Event End",
                  o_responsibilities.[WHATEVER]                     as "Team/Worker Stuff",
                  round(o_assessments.asm_start_date - o_service_events.sev_actual_date,0)
                                                                    as "Likely",
                  row_number() over (partition by o_assessments.asm_id                                    
                                     order by     abs(o_assessments.asm_start_date - o_service_events.sev_actual_date))
                                                                    as rn
        from      o_assessments 
        left join o_service_events
        on        o_service_events.sev_subject_id                    = o_assessments.asm_subject_id
        left join o_responsibilities
        on        o_responsibilities.res_rec_id                      = o_assessments.asm_id
        where     o_service_events.sev_code                         in ('ICS_E3','CPINVEST')
        and       o_assessments.asm_qsa_id                          in ('AA1329','AA521'))
where   rn = 1
and    (likely = 0 or sev_id is null);

【讨论】:

  • 这不会返回可能既不是 0 也不是 null 的评估。
  • 不,OP 没有。请参阅我对 xQbert 答案的评论以获得进一步说明。
  • 还不错;然后改成and (likely != 0 or sev_id is null);
  • 仍然无法正常工作,因为它不会返回确实具有匹配服务事件的评估。
  • 我可能在这里遗漏了一些东西——毕竟这是一个缓慢的一天! ——但在那种情况下,likely 上的额外where 子句不是无关紧要,因为它会建立一个重言式? p∨¬p 在二进制逻辑中始终为真;唯一需要考虑的其他事情是null 服务事件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2020-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多