sql完成一个结果,它在序列中遗漏了一些结果

时间:2016-11-09 13:01:28

标签: sql oracle

我有一张包含销售信息的表格

像这样:|product | sales | date|

大部分时间日期从201601年到2016年是连续的。 但有些时候存在差距:产品A的201602没有线

如何创建一个SQL查询,返回此差距的结果,如下所示:

productA,4,201601

**productA,0,201602**

productA,5,201603

productA,8,201604

(...)

而不是:

productA,4,201601

productA,5,201603

productA,8,201604

(...)

当然它也会是一些产品B,C,......

3 个答案:

答案 0 :(得分:1)

您可以使用cross join获取所有行,然后使用left join来提取值。

假设您每周都有部分数据:

select p.product, d.date, coalesce(s.sales, 0) as sales
from (select distinct product from sales) p cross join
     (select distinct date from sales) d left join
     sales s
     on s.product = p.product and s.date = d.date;

如果您有产品和日期表,则可以使用这些表而不是子查询。

答案 1 :(得分:1)

从oracle 10g开始,您可以使用partition outer join生成所需的结果:

   -- sample of data
   with sales(product, sales, dt) as(
      select 'product A', 4, 201601 from dual union all
      select 'product A', 5, 201603 from dual union all
      select 'product A', 8, 201604 from dual
    ),
    -- here we generate months for the year 2016
    mnth(dt) as(
      select 201600 + level
        from dual
      connect by level <= 12
    )
    -- actual query
    select s.product
        , nvl(s.sales, 0) as sales
        , m.dt as date1 
      from sales s
          partition by(s.product)
          right join mnth m
                 on (m.dt = s.dt)
     order by s.product, m.dt     

结果:

PRODUCT        SALES      DATE1
--------- ---------- ----------
product A          4     201601
product A          0     201602
product A          5     201603
product A          8     201604
product A          0     201605
product A          0     201606
product A          0     201607
product A          0     201608
product A          0     201609
product A          0     201610
product A          0     201611
product A          0     201612

 12 rows selected 

答案 2 :(得分:0)

基于戈登的回复,我编辑了所以日期不依赖于销售表。这里的假设是tab会有至少52行,如果不是,请使用来自oracle的相应数据字典表。

select p.product, d.date, coalesce(s.sales, 0) as sales
from (select distinct product from sales) p cross join
     (select 2016 || rownum rn from tab where rownum<=52) d left join
     sales s
     on s.product = p.product and s.date = d.date;