选择一列的最小值,另一列的最大值和最大值的字段

时间:2017-12-11 21:09:04

标签: sql oracle greatest-n-per-group

我正在尝试聚合我称之为cust_info的数据集。它看起来像这样:

ID    Sec_ID    Group_id  Cust_ID   Gender   EFF_DATE   END_DATE  
--------------------------------------------------------------------
11      H12       222       12        F       1/1/2014    12/31/2014  
11      H11       222       31        F       1/1/2015    12/31/2015  
11      H11       222       12        F       1/1/2016     4/30/2016  
11      H11       222       44        F       5/1/2016     4/30/2017  
11      H11       333       11        F       5/1/2017    12/31/9999  
22      H23       222       22        M      12/1/2015    11/30/2016  
22      H21       222       11        M       1/1/2017     6/30/2017  
22      H21       222       33        M       7/1/2017    11/30/2017

我想为每个EFF_DATEEND_DATE获得最低ID和最高sec_id。我还希望记录中的group_idcust_id最多为END_DATE

所以我最终得到了:

11      H11       333       11        F        1/1/2014    12/31/9999  
22      H21       222       33        M       12/1/2015    11/30/2017 

目前,我的代码使用min(eff_date)提取Max(end_date)group by ID, Sec_id, Grp_id, Gender。但是如果一个组有两个以上的记录,则这不起作用。此外,这是一个连接到另一个文件的内部查询。

这是我现在使用的代码:

select a.id, b.sec_id, b.group_id, b.cust_id, b.gender,  
   min(b.min_eff_date) as min_eff_date, 
   max(b.max_end_date) as max_end_date  
from first_dataset a  
left join (  
  select b.id, b.sec_id, b.group_id, b.gender, b.cust_id, 
         min(b.eff_date) as min_eff_date, 
         max(b.end_date) as max_end_date
  from cust_info b  
  group by b.id, b.sec_id, b.group_id, b.cust_id, b.gender
) b  on a.id=b.id  and 
        a.sec_id = b.sec_id

然后我使用min(min_eff_date)max(max_end_date)对上述结果进行了另一次查询。但我仍然有重复。

我想看看我是否可以在一个查询中执行此操作。我尝试了一堆ROW_NUMBER的组合。我也尝试过使用KEEP(DENSE_RANK LAST ORDER BY MAX_END_DATE)

我可以在一个查询中执行此操作吗? 我提供的数据和代码都是测试示例,真实数据涉及约300万行。

2 个答案:

答案 0 :(得分:0)

我认为以下请求可以完成这项工作:

SELECT DISTINCT a.id,
       b.sec_id,
       FIRST_VALUE(b.group_id) OVER (PARTITION BY a.id, b.sec_id GROUP BY b.end_date DESC) group_id,
       FIRST_VALUE(b.cust_id) OVER (PARTITION BY a.id, b.sec_id GROUP BY b.end_date DESC) group_id,
       b.gender,  
       min(b.eff_date) OVER (PARTITION BY a.id, b.sec_id) as min_eff_date, 
       max(b.end_date) OVER (PARTITION BY a.id, b.sec_id) as max_end_date  
  FROM first_dataset a,
       cust_info b   
 WHERE a.id = b.id (+)
   AND a.sec_id = b.sec_id (+)

答案 1 :(得分:0)

这符合您的描述:

WITH cte AS (
  SELECT row_number() OVER (PARTITION BY id, sec_id ORDER BY end_date DESC) AS rn
       , ID, Sec_ID, Group_id, Cust_ID, Gender
       , min(eff_date) OVER (PARTITION BY id, sec_id) AS EFF_DATE  -- exception
       , END_DATE
   FROM   cust_info
   )
SELECT ID, Sec_ID, Group_id, Cust_ID, Gender, EFF_DATE, END_DATE  
FROM   cte
WHERE  rn = 1;

关键元素是CTE中的analytic function ROW_NUMBER()

您的显示结果和查询目前都不符合描述。

SQL Fiddle.

相关: