Oracle SQL将多行聚合为单行

时间:2018-08-31 20:04:01

标签: sql oracle

我有一个表格,其中每个PUNCHDTM格式在1行中存储员工打卡。该表有一个SHIFTID来关联属于其班次的所有打卡机,我想要一种方法将所有单独的打卡机都放在自己的列中,从而为每个SHIFTID给我1行。我无法确定有多少拳(有些拳有2个,有些拳有10,12?),这让我觉得动态变化有些困难。如果不可能动态获得所有拳打,那么仅抓住前6个拳打就足够了。

这是一个示例数据集(我使用DENSE_RANK对每班次的上班时间进行排名)

<table border="1">
<tr><th>EMPLOYEEID </th><th> SHIFTID </th><th> SHIFTDATE  </th><th> PUNCHDTM            </th><th> RANK</th></tr>
<tr><td>0000016431 </td><td> 1400510 </td><td> 10/16/2017 </td><td> 10/16/2017 03:29 pm </td><td> 1</td></tr>
<tr><td>0000016431 </td><td> 1400510 </td><td> 10/16/2017 </td><td> 10/16/2017 08:02 pm </td><td> 2</td></tr>
<tr><td>0000016431 </td><td> 1400510 </td><td> 10/16/2017 </td><td> 10/16/2017 08:32 pm </td><td> 3</td></tr>
<tr><td>0000016431 </td><td> 1400510 </td><td> 10/16/2017 </td><td> 10/16/2017 10:30 pm </td><td> 4</td></tr>
<tr><td>0000016431 </td><td> 1404581 </td><td> 10/17/2017 </td><td> 10/17/2017 02:57 pm </td><td> 1</td></tr>
<tr><td>0000016431 </td><td> 1404581 </td><td> 10/17/2017 </td><td> 10/17/2017 07:20 pm </td><td> 2</td></tr>
</table>

和期望的结果集

<table border="1">
<tr><th>EMPLOYEEID </th><th> SHIFTID </th><th> SHIFTDATE  </th><th> PUNCHDTM1           </th><th> PUNCHDTM2           </th><th> PUNCHDTM3           </th><th> PUNCHDTM4</th></tr>
<tr><td>0000016431 </td><td> 1400510 </td><td> 10/16/2017 </td><td> 10/16/2017 03:29 pm </td><td> 10/16/2017 08:02 pm </td><td> 10/16/2017 08:32 pm </td><td> 10/16/2017 10:30 pm</td></tr>
<tr><td>0000016431 </td><td> 1404581 </td><td> 10/17/2017 </td><td> 10/17/2017 02:57 pm </td><td> 10/17/2017 07:20 pm </td><td> NULL                </td><td> NULL</td></tr>
</table>

1 个答案:

答案 0 :(得分:2)

就像您说的那样,很难动态地执行此操作,因为这将需要硬编码。但您绝对可以进行6次打孔:

select EMPLOYEEID
    , SHIFTID
    , SHIFTDATE
    , max(case when rank = 1 then PUNCHDTM else null end)  as PUNCHDTM1
    , max(case when rank = 2 then PUNCHDTM else null end)  as PUNCHDTM2
    , max(case when rank = 3 then PUNCHDTM else null end)  as PUNCHDTM3
    , max(case when rank = 4 then PUNCHDTM else null end)  as PUNCHDTM4
    , max(case when rank = 5 then PUNCHDTM else null end)  as PUNCHDTM5
    , max(case when rank = 6 then PUNCHDTM else null end)  as PUNCHDTM6
from employees
group by 1,2,3