繁体   English   中英

在Null值上处理Max函数或返回多个值

[英]Handle Max function on Null values or returning multiple values

我在下面有2个表格结构,我需要获取对应于特定事件的最大值verify_dt_tm的结果。 如果某个特定事件具有相同的verify_dt_tm,我需要根据该特定事件的最大result_id来获取它。 我在下面写了一个示例查询。 它不适用于非null值,但不适用于NULL。 我已将COALESCE用于NULL值,但由于外部查询仍将包含verify_dt_tm作为它们将不匹配的空广告,因此无法正常工作。 下面是表格的详细说明。

  • 订单表每个订单都有1个条目
  • 一个订单可以有多个结果。 例如验血可以具有嗜碱性粒细胞计数,单核细胞计数,淋巴细胞计数等,因此一个验血命令具有3个或更多事件,我可以得到相应的结果。

订单表

order_id       order_status
12345          Completed

结果表

result_table_id  order_id  event              verified_dt_tm      result_value
98765            12345     Basophils count    22/02/19 11:00      12
87654            12345     monocytes count    21/02/19 15:00      34
76543            12345     lymphocytes count  21/02/19 14:44      35
76542            12345     rbcytes count                          35
76540            12345     rbcytes count                          1
76532            12345     rbcytes count                          3

98765            12345     Basophils count    22/02/19 10:00      12
87654            12345     monocytes count    21/02/19 11:00      34
76543            12345     lymphocytes count  21/02/19 11:44      35

所需输出

result_table_id  order_id  event              verified_dt_tm      result_value
98765            12345     Basophils count    22/02/19 11:00      12
87654            12345     monocytes count    21/02/19 15:00      34
76543            12345     lymphocytes count  21/02/19 14:44      35
76542            12345     rbcytes count                          35

下面是示例查询。 此外,欢迎提出更好的查询建议:

 select o.order_id
  ,TO_CHAR(r_o.verified_dt_tm, 'DD-MON-YYYY HH24:MI:SS') as verified_dt_tm
  ,r_o.result_val as result
  ,r_o.result_table_id
  ,omf_get_cv_display(r_o.event_cd) as event
  ,omf_get_cv_display(o.ORDER_STATUS_CD) as order_status

from orders o
left outer join (select * from results r where r.event_cd > 0                                
                            and r.VERIFIED_DT_TM = (select max(COALESCE(r1.VERIFIED_DT_TM,to_date('12/31/2099','mm/dd/yyyy'))) from result r1 where r.ORDER_ID = r1.ORDER_ID
                                                    and r.EVENT_CD = r1.event_cd))r_o on r_o.ORDER_ID = o.order_id

ROW_NUMBER应该在这里可行:

WITH cte AS (
    SELECT res.*,
        ROW_NUMBER() OVER (PARTITION BY res.order_id, res.event
            ORDER BY res.verified_dt_tm DESC, res.result_value DESC) rn
    FROM orders o
    INNER JOIN result res
        ON o.order_id = r.order_id
)

SELECT *
FROM cte
WHERE rn = 1;

根据示例数据,@ Tim的上一个答案是完美的。 但是,如果该有创纪录的事件为“rbcytes计数”的一个具有非空verified_dt_tm那么也就会给输出与空verified_dt_tm为空值被递减首先考虑秩序。

查询应基于由verified_dt_tm desc nulls last的顺序计算ROW_NUMBER。

以下应该为您工作:

WITH CTE AS (
    SELECT
        RES.*,
        ROW_NUMBER() OVER(
            PARTITION BY RES.ORDER_ID, RES.EVENT
            ORDER BY
                RES.VERIFIED_DT_TM DESC NULLS LAST,  -- added NULLS LAST 
                RES.RESULT_VALUE DESC
        ) RN
    FROM
        ORDERS O
        INNER JOIN RESULT R ON O.ORDER_ID = R.ORDER_ID
)
SELECT
    *
FROM
    CTE
WHERE
    RN = 1;

干杯!!

除上述答案外,如果有人需要将其用作内联子查询的左连接,则:

left outer join (SELECT r.RESULT_VAL 
,r.EVENT
,r.result_table_ID
,r.ORDER_ID
,r.VERIFIED_DT_TM
, RANK() OVER(
    PARTITION BY r.ORDER_ID,r.EVENT ORDER BY r.VERIFIED_DT_TM DESC NULLS LAST,r.result_table_ID ) AS RANK 

from results r )r_o on (r_o.order_id = o.order_id AND r_o.RANK = 1)

如果我理解正确,则可以在Oracle中执行此操作而无需子查询。 尽管语法有点笨拙,但是Oracle在聚合中支持“第一”功能:

select max(r.result_table_id) keep (dense_rank first order by r.verified_dt_tm desc),
       r.order_id, r.event,
       max(r.verified_dt_tm),
       max(r.value) keep (dense_rank first order by r.verified_dt_tm desc, r.result_table_id desc) as value
from orders o join
     results r
     on o.order_id = r.order_id
group by r.order_id, r.event;

从性能的角度来看,为此目的使用keep可以取得良好的效果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM