我有一个这种形式的表(这只是局部视图,表包含更多列):
| 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'柱。 在完整版中,查询会复杂得多,但是现在我需要从上面描述开始。
答案 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
等不应该用作列名)。