通过基于2列中给出的范围进行分组来获取列的总和

时间:2012-12-19 16:22:54

标签: sql group-by range

我有一个sql命令,可以在以下列中显示结果

start_date, end_date, count, weekday

对于每个start_date,我想得到从start_date到其工作日匹配的end_date的计数总和。

例如,如果我有一行start_date = 2012 01 01end_date = 2012 08 08以及weekday = Tuesday,我想找到所有其他行,其start_date属于该范围内它是星期二,然后找到计数的总和。我怎样才能做到这一点?

E.g。从这张表

Start       ||  End         ||Count||  Weekday
2012-01-01  ||  2012-12-12  ||  5  ||  Tuesday
2012-05-05  ||  2012-12-12  ||  7  ||  Tuesday
2012-06-06  ||  2012-10-10  ||  2  ||  Wednesday
2012-07-07  ||  2012-08-08  ||  8  ||  Wednesday
2012-09-09  ||  2012-10-10  ||  9  ||  Tuesday

它应该返回

date        |  sum_count
2012-01-01  |  16    // count of 2012-05-05 + 2012-09-09 (Tuesdays only)
2012-05-05  |  9
2012-06-06  |  8
2012-07-07  |  0
2012-09-09  |  0

3 个答案:

答案 0 :(得分:1)

没有小提琴,sqlfiddle.com第一次尝试就很难正确。但是你想要做的就是这样做:

   select count(*), * 
   from  
   (
    select *  
    from  
       (  
           select start_date,end_date,weekday  
           from  table  
           where start_date >= timestamp('2012 01 01')  
           and end_date <=  timestamp('2012 08 08')  
        )  
       where weekday = 'Tuesday'  
    );

目标是每次都减少结果集,方法是将weekday保留在单独的子查询中,以避免代价高昂的加入或2。

问题

  

是吗?我仍然不明白。 2012 08 08,2012 01 01和   星期二来自输入表,我有多行   需要处理。你是说分别处理每一行是   效率更高?

您必须单独处理每一行,除非您知道在搜索日期时要避免全表扫描。这取决于比较我们没有的解释计划,因为我们还在等待你的小提琴 关键是,最内部的查询将为您提供所需的日期范围,以及一周中的所有日期。它更有效(大多数时候),然后针对更具体的where子句执行,在您的情况下是星期几。原因是数据库(大多数现代数据库)尝试以尽可能快地返回的方式对数据进行排序。

额外更新

作为一个真实世界的例子,我有一个表格,其中包含大约10亿个条目,我必须运行一个分析函数。我这样做的第一种方式是:

select *   
from  
(  
        select *, row_number() over (partition by id order by seen desc) rn  
        from foo  
)where rn =1  
 and status = 1

以上大约需要9分钟才能执行。当我将查询修改为:

select *
from   
(   select *   
    from  
    (  
            select *, row_number() over (partition by id order by seen desc) rn  
            from foo  
    )where status = 1  
) where status = 1

它在不到1分钟内返回。这是一个例子,我小心地减小了驱动结果集的大小,这样系统可以减少工作量,从而更快地返回。

答案 1 :(得分:1)

试试这个,我相信自我加入是最好的选择

  select b.start_date,nvl(sum(a.Count),0) from TABLE2 a right join TABLE2 b on 
  a.start_date<>b.start_date and
  a.weekday=b.weekday and a.start_date between b.start_date and b.end_date 
  group by b.start_date order by b.start_date  

fiddledemo

答案 2 :(得分:1)

我希望这是你的要求......这个用你的样本数据在oracle中运行

  select TAB.START_DATE START_DATE, nvl(X1.SUM_COUNT,0) SUM_COUNT
     from TABLE2 TAB,
        ( select A1.START_DATE,SUM(A2.COUNT) SUM_COUNT
          from TABLE2 A1,TABLE2 A2
          where A1.WEEKDAY=A2.WEEKDAY and A1.rowid <> A2.rowid
          and A2.START_DATE between A1.START_DATE and A1.END_DATE
          group by A1.START_DATE
       ) X1
    where TAB.START_DATE=X1.START_DATE(+) order by 1

请参考这个sql小提琴:http://sqlfiddle.com/#!4/2019f/4