Oracle将两行合并为一行

时间:2016-11-01 16:24:13

标签: sql oracle group-by dense-rank

我计划将两(许多)行合并为一行。我的数据看起来像这样

╔══════════╦════════╦═══════════╦═══════════╦════════════╗
║ ReportID ║  Item  ║ StartDt   ║ EndDt     ║ Statement  ║
╠══════════╬════════╬═══════════╬═══════════╬════════════╣
║  1       ║ 3000   ║ 11-Mar-16 ║ (null)    ║ Remark     ║
╠══════════╬════════╬═══════════╬═══════════╬════════════╣
║  1       ║ 3001   ║ 11-Mar-16 ║ 13-Mar-16 ║ (null)     ║
╠══════════╬════════╬═══════════╬═══════════╬════════════╣
║  2       ║ 4002   ║ 24-May-16 ║ 27-May-16 ║ Remark1    ║
╠══════════╬════════╬═══════════╬═══════════╬════════════╣
║  2       ║ 4003   ║ 24-May-16 ║ 28-May-16 ║ Remark1    ║
╚══════════╩════════╩═══════════╩═══════════╩════════════╝

我希望通过ReportID合并并使用不同的规则:

  • 使用最高endDt
  • 使用非Statement
  • null
  • 使用Statement
  • 最高记录的Item

因此,结果应为

╔══════════╦═══════════╦═══════════╦════════════╗
║ ReportID ║ StartDt   ║ EndDt     ║ Statement  ║
╠══════════╬═══════════╬═══════════╬════════════╣
║  1       ║ 11-Mar-16 ║ 13-Mar-16 ║ Remark     ║
╠══════════╬═══════════╬═══════════╬════════════╣
║  2       ║ 24-May-16 ║ 28-May-16 ║ Remark1    ║
╚══════════╩═══════════╩═══════════╩════════════╝

我需要使用纯SQL来实现这一点,并且无法编写PL-SQL例程。

数据

SELECT 1 as ReportID, 3000 as Item, TO_DATE('11-03-2016') as StartDt, TO_DATE(NULL) as EndDt, 'Remark' as Statement FROM DUAL
UNION
SELECT 1, 3001, TO_DATE('11-03-2016'), TO_DATE('13-03-2016'), NULL FROM DUAL
UNION
SELECT 2, 4002, TO_DATE('24-05-2016'), TO_DATE('27-05-2016'), 'Remark1' FROM DUAL
UNION
SELECT 2, 4003, TO_DATE('24-05-2016'), TO_DATE('28-05-2016'), 'Remark1' FROM DUAL

1 个答案:

答案 0 :(得分:5)

你想要每reportid行一行,所以你要按它分组。然后使用适当的聚合函数(语句列为KEEP FIRST/LAST)来获取所需的值:

select 
  reportid,
  max(startdt) as startdt,
  max(enddt) as enddt,
  max(statement) keep (dense_rank last 
                         order by case when statement is null then 1 else 2 end, item
                      ) as statement
from mytable
group by reportid
order by reportid;