我有一个表,该表的列为“ start_date”和“ end_date”,我试图通过在整个期间内划分日期来总结日期。例如,如果开始日期和结束日期分别为“ 01-JAN-2017”和“ 01-MAR-2018”,则查询应将每个月作为不同的字段/列返回。另外,我想查看此期间每个月出现的次数/发生次数,即JAN,FEB和MAR等月份的值应为2,因为它们在“ 01-JAN-2017”和“ 2018年3月1日”。
例如,如果start_date = '01 -JAN-2018'和end_date = '31 -MAR-2019',则输出应为:
jan | feb | mar | apr | may | jun | jul | aug | sep | oct | nov | dec
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1
答案 0 :(得分:0)
这应该使您入门。这是我必须做的一个示例,用于将员工的登记入住和退房时间划分为一天,但是这个概念是相似的。我们合成中间数据,然后转到行中
SQL> create table t
2 ( emp int,
3 in_time date,
4 out_time date );
Table created.
SQL>
SQL>
SQL> insert into t values (1, trunc(sysdate)+1.5/24, trunc(sysdate)+3.5/24);
1 row created.
SQL> insert into t values (1, trunc(sysdate)+5.4/24, trunc(sysdate)+9.5/24);
1 row created.
SQL> insert into t values (1, trunc(sysdate)+10/24, trunc(sysdate)+11/24);
1 row created.
SQL>
SQL> insert into t values (2, trunc(sysdate)+2.2/24, trunc(sysdate)+3.5/24);
1 row created.
SQL> insert into t values (2, trunc(sysdate)+5/24, trunc(sysdate)+7/24);
1 row created.
SQL> insert into t values (2, trunc(sysdate)+10.7/24, trunc(sysdate)+11.2/24);
1 row created.
SQL> insert into t values (2, trunc(sysdate)+9.2/24, trunc(sysdate)+9.4/24);
1 row created.
SQL>
SQL> @longdate
Session altered.
SQL>
SQL> select
2 emp,
3 in_time,
4 out_time,
5 to_number(to_char(in_time,'HH24')) as in_hr,
6 to_number(to_char(out_time,'HH24')) as out_hr,
7 to_number(to_char(in_time,'MI')) as in_min,
8 to_number(to_char(out_time,'MI')) as out_min
9 from t;
EMP IN_TIME OUT_TIME IN_HR OUT_HR IN_MIN OUT_MIN
---------- ------------------- ------------------- ---------- ---------- ---------- ----------
1 12/07/2019 01:30:00 12/07/2019 03:30:00 1 3 30 30
1 12/07/2019 05:24:00 12/07/2019 09:30:00 5 9 24 30
1 12/07/2019 10:00:00 12/07/2019 11:00:00 10 11 0 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 2 3 12 30
2 12/07/2019 05:00:00 12/07/2019 07:00:00 5 7 0 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 10 11 42 12
2 12/07/2019 09:12:00 12/07/2019 09:24:00 9 9 12 24
7 rows selected.
SQL>
SQL> with t_extended as
2 ( select
3 emp,
4 in_time,
5 out_time,
6 to_number(to_char(in_time,'HH24')) as in_hr,
7 to_number(to_char(out_time,'HH24')) as out_hr,
8 to_number(to_char(in_time,'MI')) as in_min,
9 to_number(to_char(out_time,'MI')) as out_min
10 from t
11 ),
12 hr_of_day as
13 ( select level-1 hr from dual connect by level <= 24 )
14 select
15 e.emp,
16 e.in_time,
17 e.out_time,
18 h.hr,
19 case
20 -- totally outside range
21 when in_hr > hr then 0
22 when out_hr < hr then 0
23 -- less than 1 hour
24 when in_hr = hr and out_hr = hr then out_min - in_min
25 -- ends on hour
26 when in_hr < hr and out_hr = hr then out_min
27 -- start on hour
28 when in_hr = hr and out_hr > hr then 60 - in_min
29 -- contained
30 when in_hr < hr and out_hr > hr then 60
31 end dur
32 from t_extended e, hr_of_day h
33 order by 1,2,4;
EMP IN_TIME OUT_TIME HR DUR
---------- ------------------- ------------------- ---------- ----------
1 12/07/2019 01:30:00 12/07/2019 03:30:00 0 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 1 30
1 12/07/2019 01:30:00 12/07/2019 03:30:00 2 60
1 12/07/2019 01:30:00 12/07/2019 03:30:00 3 30
1 12/07/2019 01:30:00 12/07/2019 03:30:00 4 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 5 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 6 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 7 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 8 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 9 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 10 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 11 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 12 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 13 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 14 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 15 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 16 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 17 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 18 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 19 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 20 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 21 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 22 0
1 12/07/2019 01:30:00 12/07/2019 03:30:00 23 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 0 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 1 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 2 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 3 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 4 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 5 36
1 12/07/2019 05:24:00 12/07/2019 09:30:00 6 60
1 12/07/2019 05:24:00 12/07/2019 09:30:00 7 60
1 12/07/2019 05:24:00 12/07/2019 09:30:00 8 60
1 12/07/2019 05:24:00 12/07/2019 09:30:00 9 30
1 12/07/2019 05:24:00 12/07/2019 09:30:00 10 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 11 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 12 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 13 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 14 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 15 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 16 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 17 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 18 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 19 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 20 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 21 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 22 0
1 12/07/2019 05:24:00 12/07/2019 09:30:00 23 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 0 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 1 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 2 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 3 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 4 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 5 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 6 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 7 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 8 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 9 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 10 60
1 12/07/2019 10:00:00 12/07/2019 11:00:00 11 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 12 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 13 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 14 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 15 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 16 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 17 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 18 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 19 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 20 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 21 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 22 0
1 12/07/2019 10:00:00 12/07/2019 11:00:00 23 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 0 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 1 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 2 48
2 12/07/2019 02:12:00 12/07/2019 03:30:00 3 30
2 12/07/2019 02:12:00 12/07/2019 03:30:00 4 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 5 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 6 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 7 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 8 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 9 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 10 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 11 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 12 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 13 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 14 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 15 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 16 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 17 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 18 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 19 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 20 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 21 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 22 0
2 12/07/2019 02:12:00 12/07/2019 03:30:00 23 0
EMP IN_TIME OUT_TIME HR DUR
---------- ------------------- ------------------- ---------- ----------
2 12/07/2019 05:00:00 12/07/2019 07:00:00 0 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 1 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 2 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 3 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 4 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 5 60
2 12/07/2019 05:00:00 12/07/2019 07:00:00 6 60
2 12/07/2019 05:00:00 12/07/2019 07:00:00 7 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 8 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 9 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 10 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 11 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 12 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 13 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 14 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 15 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 16 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 17 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 18 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 19 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 20 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 21 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 22 0
2 12/07/2019 05:00:00 12/07/2019 07:00:00 23 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 0 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 1 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 2 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 3 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 4 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 5 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 6 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 7 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 8 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 9 12
2 12/07/2019 09:12:00 12/07/2019 09:24:00 10 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 11 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 12 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 13 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 14 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 15 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 16 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 17 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 18 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 19 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 20 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 21 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 22 0
2 12/07/2019 09:12:00 12/07/2019 09:24:00 23 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 0 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 1 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 2 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 3 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 4 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 5 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 6 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 7 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 8 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 9 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 10 18
2 12/07/2019 10:42:00 12/07/2019 11:12:00 11 12
2 12/07/2019 10:42:00 12/07/2019 11:12:00 12 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 13 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 14 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 15 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 16 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 17 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 18 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 19 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 20 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 21 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 22 0
2 12/07/2019 10:42:00 12/07/2019 11:12:00 23 0
168 rows selected.
SQL>
SQL> with t_extended as
2 ( select
3 emp,
4 in_time,
5 out_time,
6 to_number(to_char(in_time,'HH24')) as in_hr,
7 to_number(to_char(out_time,'HH24')) as out_hr,
8 to_number(to_char(in_time,'MI')) as in_min,
9 to_number(to_char(out_time,'MI')) as out_min
10 from t
11 ),
12 hr_of_day as
13 ( select level-1 hr from dual connect by level <= 24 ),
14 raw_data as (
15 select
16 e.emp,
17 e.in_time,
18 e.out_time,
19 h.hr,
20 case
21 -- totally outside range
22 when in_hr > hr then 0
23 when out_hr < hr then 0
24 -- less than 1 hour
25 when in_hr = hr and out_hr = hr then out_min - in_min
26 -- ends on hour
27 when in_hr < hr and out_hr = hr then out_min
28 -- start on hour
29 when in_hr = hr and out_hr > hr then 60 - in_min
30 -- contained
31 when in_hr < hr and out_hr > hr then 60
32 end dur
33 from t_extended e, hr_of_day h
34 --order by 1,2,4
35 )
36 select *
37 from ( select emp, hr, dur from raw_data )
38 pivot ( sum(dur) as t for (hr) in ( 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23))
39 /
EMP 0_T 1_T 2_T 3_T 4_T 5_T 6_T 7_T 8_T 9_T
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
10_T 11_T 12_T 13_T 14_T 15_T 16_T 17_T 18_T 19_T 20_T
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
21_T 22_T 23_T
---------- ---------- ----------
1 0 30 60 30 0 36 60 60 60 30
60 0 0 0 0 0 0 0 0 0 0
0 0 0
2 0 0 48 30 0 60 60 0 0 12
18 12 0 0 0 0 0 0 0 0 0
0 0 0
SQL>
SQL>
答案 1 :(得分:0)
在下面的解决方案中,range_start和range_end日期被硬编码在with
子句(子查询)中。您可以更改这些值,例如绑定变量,以允许用户输入。
在主查询中,按照通常的方式(一个connect by
查询)创建一个值从1到12的小表,并使用pivot
运算符将结果对齐一行pivot
是Oracle 11.1中引入的,因此您很可能可以使用它,但是如果您的版本较旧,则存在其他透视方法,同样可以很好地发挥作用。
解决方案的核心是pivot
的第一部分中的数学计算。我不会在这里解释数学(如果不是很清楚),因为这是一个编程论坛,而不是算术论坛。
with
test_data as (
select to_date('01-JAN-2017', 'dd-MON-yyyy') as range_start,
to_date('31-MAR-2018', 'dd-MON-yyyy') as range_end
from dual
)
select *
from (select level as mth from dual connect by level <= 12)
cross join test_data
pivot (min(extract(year from range_end) - extract(year from range_start) + 1
- case when extract(month from range_start) > mth then 1 else 0 end
- case when extract(month from range_end) < mth then 1 else 0 end)
for mth in (1 jan, 2 feb, 3 mar, 4 apr, 5 may, 6 jun, 7 jul, 8 aug, 9 sep,
10 oct, 11 nov, 12 dec))
;
输出
JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
--- --- --- --- --- --- --- --- --- --- --- ---
2 2 2 1 1 1 1 1 1 1 1 1