即使缺少几个月,我也需要所有24个月的数据。
样本数据
id custname reportdate sales
1 xx 31-JAN-17 1256
1 xx 31-MAR-17 3456
1 xx 30-JUN-17 5678
1 xx 31-DEC-17 6785
2 xx 31-JAN-17 1223
2 xx 31-APR-17 3435
2 xx 30-JUN-17 6777
2 xx 31-DEC-17 9643
我需要什么作为输出
id custname reportdate sales
1 xx JAN-17 1256
1 xx FEB-17 <null>
1 xx MAR-17 3456
.....................................
.....................................
1 xx DEC-17 6785
对于ID 2 ....
尝试了这种运气
select CUSTNAME, reportdate, sales from
(
select TRIM( LEADING '0' FROM TO_CHAR( statementdate, 'YYYY-MM') ) AS REPORTDATE mm, CUSTNAME
froM MYTABLE) SALES,
(
select to_char(date '2017-01-01' + numtoyminterval(level,'month'), 'mm') MonthName
--i actually need format as MON-Last 2 digit of year eg:JAN-17
from dual
connect by level <= 24) ALLMONTHS
where mm = MonthName(+)
也尝试过使用CTE,但我无法通过外部联接使用my_year.year_month CTE
my_year as (
select date '2017-01-31' start_date,date '2018-12-31' end_date from dual
)
select (to_char(add_months(trunc(start_date,'mm'),level - 1),'yyyy')||'-'||(to_char(add_months(trunc(start_date,'mm'),level - 1),'mm'))) year_month
from my_year
connect by trunc(end_date,'mm') >= add_months(trunc(start_date,'mm'),level - 1);
select id, customername, reportdate, sales,
TRIM( LEADING '0' FROM TO_CHAR( reportdate, 'YYYY-MM') ) AS stmntdate
from my_oracle_tbl a
where a.stmntdate = my_year.year_month (+)
还按照@Littlefoot的建议尝试了此操作,该方法不起作用
WITH mydates AS (
select LAST_DAY(add_months(date '2017-01-01', level - 1)) as mth, min_id,min_custname
from (
select min(id) as min_id, min(CUSTNAME) as min_custname
from my_oracle_tbl
)
connect by level <= 24)
select
nvl(t.id, a.min_id)id,
nvl(t.CUSTNAME,a.min_custname)CUSTNAME, a.mth, t.sales
from mydates a left join my_oracle_tbl t on a.mth= LAST_DAY(t.reporttdate)
where
t.id=2
;
答案 0 :(得分:0)
这是一个例子;看看是否有帮助。它显示12个月(您将在第21行中将其替换为24个月)。
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test (id, custname, reportdate, sales) as
2 (select 1, 'xx', date '2017-01-31', 1256 from dual union all
3 select 1, 'xx', date '2017-03-31', 3456 from dual union all
4 select 1, 'xx', date '2017-06-30', 5678 from dual union all
5 --
6 select 2, 'xx', date '2017-03-31', 1223 from dual union all
7 select 2, 'xx', date '2017-07-31', 3435 from dual union all
8 select 2, 'xx', date '2017-09-30', 6777 from dual
9 ),
10 all_dates as
11 (select add_months(min_repdate, column_value - 1) c_mon,
12 min_id,
13 min_custname
14 from (select min(reportdate) min_repdate,
15 id min_id,
16 min(custname) min_custname
17 from test
18 group by id
19 ),
20 table(cast(multiset(select level from dual
21 connect by level <= 12
22 ) as sys.odcinumberlist))
23 )
24 select nvl(t.id, a.min_id) id,
25 nvl(t.custname, a.min_custname) custname,
26 a.c_mon,
27 t.sales
28 from all_dates a left join test t on a.min_id = t.id and a.c_mon = t.reportdate
29 order by id, a.c_mon;
ID CU C_MON SALES
---------- -- ---------- ----------
1 xx 31.01.2017 1256
1 xx 28.02.2017
1 xx 31.03.2017 3456
1 xx 30.04.2017
1 xx 31.05.2017
1 xx 30.06.2017 5678
1 xx 31.07.2017
1 xx 31.08.2017
1 xx 30.09.2017
1 xx 31.10.2017
1 xx 30.11.2017
1 xx 31.12.2017
2 xx 31.03.2017 1223
2 xx 30.04.2017
2 xx 31.05.2017
2 xx 30.06.2017
2 xx 31.07.2017 3435
2 xx 31.08.2017
2 xx 30.09.2017 6777
2 xx 31.10.2017
2 xx 30.11.2017
2 xx 31.12.2017
2 xx 31.01.2018
2 xx 28.02.2018
24 rows selected.
SQL>
答案 1 :(得分:0)
您可以使用一些老式的技巧(将所有元素与ADD_MONTHS功能和总和结合在一起):
select id, custname,month,
decode(sum(sales),0,null,sum(sales)) sales from
(select id, custname, to_char(reportdate, 'mon-rrrr')
month,sales from my_oracle_tbl
UNION ALL
select a.*,b.*,0 sales from
(select distinct id, custname from my_oracle_tbl) a,
(
select to_char(sysdate,'mon')||'-2017' month from dual
UNION ALL
select ,to_char(add_months(sysdate,1),'mon')||'-2017' month from dual
UNION ALL
select ,to_char(add_months(sysdate,2),'mon')||'-2017' from dual
.......
UNION ALL
select ,to_char(add_months(sysdate,11),'mon')||'-2017' from dual) b
)
group by id, custname,month;
答案 2 :(得分:0)
这就是我想到的,您是否有任何担忧?有没有更好的方法来写这个?我需要从最低日期到最大日期获得订单?我怎么能做到这一点。截至目前,它重复这样的订单12-2018,12-2017,11-2018,11-2017。我想先2017年,然后2018年
select CUSTNAME, reportdate, sum(sales), mth
from ( select to_char(add_months(date '2017-01-01', level - 1), 'mmyyyy') mth
from dual
connect by level <= 24)mo
left outer join oracle_tbl dc on mo.mth = to_char(reportdate, 'mmyyyy')
group by CUSTNAME, reportdate,mth
order by mth