0

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

start_date, end_date, count, weekday

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

例如,如果我有一个带有start_date = 2012 01 01andend_date = 2012 08 08的行weekday = Tuesday,我想找到所有其他行的 start_date 落在该范围内并且它是星期二,然后找到计数的总和。我怎样才能做到这一点?

例如从这张表

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
4

3 回答 3

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 和 Tuesday 来自输入表,我需要处理多行。您是说单独处理每一行更有效吗?

您必须单独处理每一行,除非您知道在搜索日期时以某种方式避免全表扫描。这取决于比较解释计划,因为我们仍在等待您的小提琴,所以我们没有。
关键是最内部的查询将为您提供所需的日期范围,以及一周中的所有日期。然后针对更具体的 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 分钟的时间内返回。这是一个示例,我小心地减小了驱动结果集的大小,以便系统做更少的工作,从而更快地返回。

于 2012-12-19T16:29:06.417 回答
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  

小提琴演示

于 2012-12-19T16:29:37.867 回答
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 fiddle:http ://sqlfiddle.com/#!4/2019f/4

于 2012-12-20T12:25:17.023 回答