Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 即使我们错过了几个月,也可以轻松获取2年的月份数据_Sql_Oracle - Fatal编程技术网

Sql 即使我们错过了几个月,也可以轻松获取2年的月份数据

Sql 即使我们错过了几个月,也可以轻松获取2年的月份数据,sql,oracle,Sql,Oracle,我需要获取所有显示的24个月,即使缺少相应销售值为空的月份。这就是我想到的。正如你所看到的,我们缺少id和客户名称。我需要id和custname,其中sales为null,如下面的屏幕截图所示 我还尝试了以下方法,但似乎没有任何效果,即为custname和id提供空值,因为它们缺少日期 WITH mydates AS ( select LAST_DAY(add_months(date '2017-01-01', level - 1)) as mth, min_id,min_custna

我需要获取所有显示的24个月,即使缺少相应销售值为空的月份。这就是我想到的。正如你所看到的,我们缺少id和客户名称。我需要id和custname,其中sales为null,如下面的屏幕截图所示

我还尝试了以下方法,但似乎没有任何效果,即为custname和id提供空值,因为它们缺少日期

 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=12345;


  select CUSTNAME, reportdate, sales, mth
  from( SELECT CUSTNAME, reportdate, sales, mth FROM my_oracle_tbl
  WHERE id=123 )
 myTotals
       right outer join
       (select LAST_DAY(date '2017-01-01' + numtoyminterval(level-1,'month')) MonthName
          from dual
       connect by level <= 24) ALLMONTHS
       on( myTotals.mm = allmonths.MonthName )
[![我就是这样得到的..缺少id和客户名][1][1]


[![这就是我所需要的][2][2]

您没有说确切的错误,但您是按字符串值订购的,因此您将得到2017年1月、2018年1月、2017年2月

将日期保留为实际日期,直到您需要以固定格式显示或让您的客户这样做。这包括进行比较

select dc.CUSTNAME, dc.reportdate, dc.sales, mo.mth
from (
  select add_months(date '2017-01-01', level - 1) as mth 
  from dual 
  connect by level <= 24
) mo
left outer join oracle_tbl dc on mo.mth = trunc(dc.reportdate, 'MM')
order by mo.mth

无论哪种方式,你都会得到一个日期,然后你可以按照你想要的格式来显示它——如果你真的想显示它的话。

假设我们有以下表格:{1}个日期,包含你需要的所有月份的最后一天,{2}个销售,包含不是每个月的客户销售额

create table dates ( month_end_date ) 
as
select add_months(date '2017-01-01', level - 1) - 1
from dual
connect by level <= 24 ; 

create table sales (customerid, custname, sales, date_of_sale ) 
as
select *
from (
  select
    case when mod( level, 3 ) = 0 then 1 end as customerid
  , case when mod( level, 3 ) = 0 then 'test' end
  , case when mod( level, 3 ) = 0 then trunc( dbms_random.value() * 10000 ) end
  , case when mod( level, 3 ) = 0 then add_months(date '2017-01-01', level - 1) end
  from dual connect by level <= 24
) 
where customerid is not null ;
日期表

SQL> select * from dates ;

MONTH_END
---------
31-DEC-16
31-JAN-17
28-FEB-17
31-MAR-17
30-APR-17
...
31-JUL-18
31-AUG-18
30-SEP-18
31-OCT-18
30-NOV-18

24 rows selected. 
下面的查询应该为您提供一些可以从中工作的内容。。。交叉连接提供所有组合 客户ID+客户名称和月末日期的组合。左连接输出所需的所有空值。请注意,我们在join条件中调用了LAST_DAY。您也可以使用选择。。。通过…连接。。。如您在自己的查询中所做的,用于生成所有月末日期

select CM.customerid, CM.custname, S.sales, CM.month_end_date
from (
  select *
  from (
    ( select unique customerid, custname from sales )
    cross join
    ( select month_end_date from dates )  -- <- data could be "generated"
  ) 
) CM left join sales S on CM.month_end_date = last_day( S.date_of_sale ) 
order by CM.month_end_date
;
编辑限制日期范围,按客户筛选

要处理多个客户,并缩小结果集的日期范围,请在左JOIN的ON子句中添加一个条件,然后在WHERE子句中添加更多条件,例如

销售测试表

-- New SALES table for testing
-- 5 customers, 1 sale every 5 months (per customer)
create table sales (customerid, custname, sales, date_of_sale ) 
as
select *
from (
  select
    mod( level, 5 ) + 1
  , 'test' || to_char( mod( level, 5 ) + 1 )
  , trunc( dbms_random.value() * 10000 )
  , add_months(date '2017-01-01', level - 1)
  from dual connect by level <= 24
) 
;
质疑


你能提供样本数据和结果吗?@Rika,谢谢。问题是上面的ID也丢失了。我需要24个月的所有属性,缺少的销售月为空。我还尝试为23个月创建一个临时视图,并执行外部连接b/w表和日期视图,但不起作用。我如何获得所有价值,除了丢失月份的重复销售。谢谢。但是上面的PartitionBy导致了错误的结果1它不允许我筛选特定的客户id,2它给出了超出我们日期的所有可用年份tables@sunnybabau-如果无法使分区正常工作,请不要费心。请参见编辑:查询应允许您根据需要筛选结果。@sunnybabau-外部联接(无论是左联接还是右联接)不会生成缺少的日期。这就是为什么我建议将交叉连接与左连接相结合。另一个示例是仅使用SALES表,但没有专用日期表:
SQL> select * from dates ;

MONTH_END
---------
31-DEC-16
31-JAN-17
28-FEB-17
31-MAR-17
30-APR-17
...
31-JUL-18
31-AUG-18
30-SEP-18
31-OCT-18
30-NOV-18

24 rows selected. 
select CM.customerid, CM.custname, S.sales, CM.month_end_date
from (
  select *
  from (
    ( select unique customerid, custname from sales )
    cross join
    ( select month_end_date from dates )  -- <- data could be "generated"
  ) 
) CM left join sales S on CM.month_end_date = last_day( S.date_of_sale ) 
order by CM.month_end_date
;
CUSTOMERID CUST      SALES MONTH_END
---------- ---- ---------- ---------
         1 test NULL       31-DEC-16
         1 test NULL       31-JAN-17
         1 test NULL       28-FEB-17
         1 test       5764 31-MAR-17
         1 test NULL       30-APR-17
         1 test NULL       31-MAY-17
         1 test       3937 30-JUN-17
         1 test NULL       31-JUL-17
         1 test NULL       31-AUG-17
         1 test       9926 30-SEP-17
         1 test NULL       31-OCT-17
         1 test NULL       30-NOV-17
         1 test       3045 31-DEC-17
         1 test NULL       31-JAN-18
         1 test NULL       28-FEB-18
         1 test        598 31-MAR-18
         1 test NULL       30-APR-18
         1 test NULL       31-MAY-18
         1 test        325 30-JUN-18
         1 test NULL       31-JUL-18
         1 test NULL       31-AUG-18
         1 test       2590 30-SEP-18
         1 test NULL       31-OCT-18
         1 test NULL       30-NOV-18
-- caution:       sale for 01-DEC-18 "chopped off"
24 rows selected. 
-- New SALES table for testing
-- 5 customers, 1 sale every 5 months (per customer)
create table sales (customerid, custname, sales, date_of_sale ) 
as
select *
from (
  select
    mod( level, 5 ) + 1
  , 'test' || to_char( mod( level, 5 ) + 1 )
  , trunc( dbms_random.value() * 10000 )
  , add_months(date '2017-01-01', level - 1)
  from dual connect by level <= 24
) 
;
SQL> select * from sales;

CUSTOMERID  CUSTNAME  SALES  DATE_OF_SALE  
2           test2     5594   01-JAN-17     
3           test3     6398   01-FEB-17     
4           test4     2072   01-MAR-17     
5           test5     4269   01-APR-17     
1           test1     9435   01-MAY-17     
2           test2     6984   01-JUN-17     
3           test3     5735   01-JUL-17     
4           test4     9549   01-AUG-17     
5           test5     9686   01-SEP-17     
1           test1     9193   01-OCT-17     
2           test2     1702   01-NOV-17     
3           test3     8277   01-DEC-17     
4           test4     8235   01-JAN-18     
5           test5     7596   01-FEB-18     
1           test1     5507   01-MAR-18     
2           test2     6267   01-APR-18     
3           test3     5708   01-MAY-18     
4           test4     755    01-JUN-18     
5           test5     3966   01-JUL-18     
1           test1     5167   01-AUG-18     
2           test2     6819   01-SEP-18     
3           test3     9268   01-OCT-18     
4           test4     1844   01-NOV-18     
5           test5     1085   01-DEC-18     

24 rows selected.
-- sales for customer (id) 3, between 30 Apr 2018 and 31 Dec 2018
select CM.customerid, CM.custname, S.sales, CM.month_end_date
from (
  select *
  from (
    ( select unique customerid, custname from sales )
    cross join
    ( select month_end_date from dates )
  ) 
) CM 
  left join sales S 
         on CM.month_end_date = last_day( S.date_of_sale )
           and CM.customerid = S.customerid  
where CM.customerid = 3
  and CM.month_end_date > date '2018-04-30'
  and CM.month_end_date < date '2018-12-31'
order by CM.month_end_date
;

-- result
CUSTOMERID  CUSTNAME  SALES  MONTH_END_DATE  
3           test3     5708   31-MAY-18       
3           test3     NULL   30-JUN-18       
3           test3     NULL   31-JUL-18       
3           test3     NULL   31-AUG-18       
3           test3     NULL   30-SEP-18       
3           test3     9268   31-OCT-18       
3           test3     NULL   30-NOV-18