通过Oracle

时间:2017-08-28 19:50:39

标签: sql oracle select

我有一个这种形式的表(这只是局部视图,表包含更多列):

| USER     | date_of        | duration |  
|----------|----------------|----------|  
| John     |   01.08.2017   |   5      |  
| Anna     |   01.08.2017   |   6      |  
| John     |   03.08.2017   |   10     |      
| Anna     |   05.08.2017   |   7      |     
| Eugene   |   30.08.2017   |   16     | 

我需要一个查询(select),它将返回以下格式的数据:

|USER    | 01| 02| 03| 04| 05| 06| ... | 29| 30| 31|Total|Count| 
|--------|---|---|---|---|---|---|-----|---|---|---|-----|-----|  
|Anna    |  6|   |   |   |  7|   |     |   |   |   |  13 |   2 |  
|John    |  5|   | 10|   |   |   |     |   |   |   |  15 |   1 |  
|Eugene  |   |   |   |   |   |   |     |   | 16|   |  16 |   1 |  

所以,我需要在时间表中填写01..31列(月份,2月28/29,8月31日等)的实际数据,空白时为空,计算每个的总小时数。用户在列'总计'并将持续时间超过5天的天数计入' Count'柱。 在完整版中,查询会复杂得多,但是现在我需要从上面描述开始。

1 个答案:

答案 0 :(得分:1)

这听起来像PIVOT,除了你还需要一些聚合。这可以通过GROUP BY ROLLUP或其他类似的聚合扩展来完成,虽然它更复杂,因为你想要一个TOTAL和一个条件 COUNT。

使用"手册"一切都很简单(但很乏味)转向 - 在Oracle 11.1中引入PIVOT运算符之前,每个人都必须做的事情。这样做的好处是它可以在早期版本中使用,并且 - 虽然还有更多要编写的内容 - 如果需要,将来更容易修改。

with
     inputs ( usr, date_of, duration ) as ( 
       select 'John'  , to_date('01.08.2017', 'dd.mm.yyyy'),  5 from dual union all
       select 'Ann'   , to_date('01.08.2017', 'dd.mm.yyyy'),  6 from dual union all
       select 'John'  , to_date('03.08.2017', 'dd.mm.yyyy'), 10 from dual union all
       select 'Ann'   , to_date('05.08.2017', 'dd.mm.yyyy'),  7 from dual union all
       select 'Eugene', to_date('30.08.2017', 'dd.mm.yyyy'), 16 from dual
     )
-- End of simulated data (for testing only, not part of the solution).
-- Use your own table and column names in the SQL query below.
select   usr,
         sum(case extract(day from date_of) when  1 then duration end) as "01",
         sum(case extract(day from date_of) when  2 then duration end) as "02",
         sum(case extract(day from date_of) when  3 then duration end) as "03",
 --        .............
 --        .............
         sum(case extract(day from date_of) when 31 then duration end) as "31",
         sum(duration) as total_duration,
         count(case when duration > 5 then 1 end) as cnt
from     inputs
group by usr
;

部分输出(到目前为止在图中包含的列):

USR     01  02  03  31  TOTAL_DURATION  CNT
------  --  --  --  --  --------------  ---
John     5      10                  15    1
Eugene                              16    1
Ann      6                          13    2

USER和COUNT是保留字,不要在输入和输出中将它们用作列名。最好不要使用双引号列名(这意味着01等不应该用作列名)。