sq如何在两个日期之间每周获得总和值?

时间:2016-10-04 10:40:38

标签: sql oracle oracle11g oracle10g

我的表值如......

Date    Amt Cash    Money   Name
15-Jun  100 10  20  GUL
16-Jun  200 20  40  ABC
20-Jun  300 30  60  GUL
25-Jun  400 40  80  BCA
28-Jun  500 50  10  GUL
3-Jul   600 60  120 ABC
19-Jun  700 70  140 BCA
26-Jun  800 80  160 ABC
7-Jul   900 90  180 GUL
9-Jul   1000    100 200 ABC

我需要每周返回oracle中两个日期之间的值之和。我的预期输出。

Date            Amt    Cash Mony
13 to 19 June   1000    100 200
20 to 26 June   1500    150 300
27 to3 July     1100    110 130
4 to 10 July    1900    190 380

3 个答案:

答案 0 :(得分:1)

您可以通过案例陈述来实现这一目标:

e.g。

-- test data
with data(dat,
val1,
val2) as
 (select sysdate - 7, 12, 13
    from dual
  union all
  select sysdate - 6, 32, 1
    from dual
  union all
  select sysdate - 5, 52, 53
    from dual
  union all
  select sysdate - 4, 2, 16
    from dual
  union all
  select sysdate - 3, 72, 154
    from dual)

select -- build up your groups
       case
         when d.dat < to_date('28.09.2016', 'DD.MM.YYYY') then
          '<28.09.'
         when d.dat > to_date('30.09.2016', 'DD.MM.YYYY') then
          '>30.09.'
         else
          '28.-30.'
       end as grp,
       sum(val1),
       sum(val2)
  from data d
 group by case
            when d.dat < to_date('28.09.2016', 'DD.MM.YYYY') then
             '<28.09.'
            when d.dat > to_date('30.09.2016', 'DD.MM.YYYY') then
             '>30.09.'
            else
             '28.-30.'
          end;

-- output
grp sum(val1) sum(val2)
28.-30. 84  54
<28.09. 12  13
>30.09. 74  170

按日历周分组使用

-- test data
with data(dat,
val1,
val2) as
 (select sysdate - 9, 12, 13
    from dual
  union all
  select sysdate - 6, 32, 1
    from dual
  union all
  select sysdate - 5, 52, 53
    from dual
  union all
  select sysdate - 4, 2, 16
    from dual
  union all
  select sysdate + 3, 72, 154
    from dual)

select TRUNC(dat, 'iw') ||'-'|| TRUNC(dat+7, 'iw'),
sum(val1),
sum(val2)
from data
group by TRUNC(dat, 'iw') ||'-'|| TRUNC(dat+7, 'iw');

答案 1 :(得分:0)

您可以尝试如下,我选择2016年6月13日作为开始日期。您可以根据您的要求选择任何日期范围。

with t as
(select dt,
        min(dt) over (partition by week)||' to '|| max(dt) over (partition by week) week
 from (
       select to_date('13-Jun-2016','dd-Mon-yyyy')+(level-1) dt,
              ceil(level/7) week
       from   dual
       connect by level<=52)) 
select week,
       sum(amt),
       sum(cash),
       sum(money)
from (
select your_table.*,
       t.week
from   your_table,t
where  trunc(to_date(your_table.dt,'dd-Mon-yyyy'))=trunc(t.dt))
group by week;

答案 2 :(得分:0)

下面的查询在第一个因子子查询中有输入日期(从和到)。这些可以被制作为绑定变量,或者您想要用于将这些输入传递给查询的任何机制。然后我在第二个因子子查询中得到测试数据;你不需要在最终的解决方案中。我在&#34;周&#34;中创造了所需的所有周。因子子查询和我使用左外连接,因此没有交易的周将显示0总和。请注意,在主查询中,我在哪里进行连接,&#34; date&#34;基表中的列未包含在任何类型的函数中;这允许在该列上使用索引,如果表非常大,或者由于任何其他原因可能需要考虑性能,则应该使用该索引。请注意,输出与您的输出不同(缺少最后一行),因为我在表的最后一行之前输入了to-date。这是故意的,我想确保查询正常工作。另外:我没有使用&#34; date&#34;或者&#34;周&#34;作为列名;这是一个非常糟糕的做法。保留的Oracle关键字不应用作列名。我用了#34; dt&#34;和&#34; wk&#34;代替。

with
     user_inputs ( from_dt, to_dt ) as (
       select to_date('4-Jun-2016', 'dd-Mon-yyyy'), to_date('3-Jul-2016', 'dd-Mon-yyyy') from dual
     ),
     test_data ( dt, amt, cash, money, name ) as (
       select to_date('15-Jun-2016', 'dd-Mon-yyyy'),  100,  10,  20, 'GUL' from dual union all
       select to_date('16-Jun-2016', 'dd-Mon-yyyy'),  200,  20,  40, 'ABC' from dual union all
       select to_date('20-Jun-2016', 'dd-Mon-yyyy'),  300,  30,  60, 'GUL' from dual union all
       select to_date('25-Jun-2016', 'dd-Mon-yyyy'),  400,  40,  80, 'BCA' from dual union all
       select to_date('28-Jun-2016', 'dd-Mon-yyyy'),  500,  50,  10, 'GUL' from dual union all
       select to_date( '3-Jul-2016', 'dd-Mon-yyyy'),  600,  60, 120, 'ABC' from dual union all
       select to_date('19-Jun-2016', 'dd-Mon-yyyy'),  700,  70, 140, 'BCA' from dual union all
       select to_date('26-Jun-2016', 'dd-Mon-yyyy'),  800,  80, 160, 'ABC' from dual union all
       select to_date( '7-Jul-2016', 'dd-Mon-yyyy'),  900,  90, 180, 'GUL' from dual union all
       select to_date( '9-Jul-2016', 'dd-Mon-yyyy'), 1000, 100, 200, 'ABC' from dual
     ),
     weeks ( start_dt ) as (
       select trunc(from_dt, 'iw') + 7 * (level - 1)
       from   user_inputs
       connect by level <= 1 + (to_dt - trunc(from_dt, 'iw')) / 7
     )
select to_char(w.start_dt, 'dd-Mon-yyyy') || ' - ' || 
                                 to_char(w.start_dt + 6, 'dd-Mon-yyyy') as wk,
       nvl(sum(t.amt), 0) as tot_amt, nvl(sum(t.cash), 0) as tot_cash, 
                                          nvl(sum(t.money), 0) as tot_money
from   weeks w left outer join test_data t
               on t.dt >= w.start_dt and t.dt < w.start_dt + 7
group by start_dt
order by start_dt
;

<强>输出

WK                                              TOT_AMT   TOT_CASH  TOT_MONEY
-------------------------------------------- ---------- ---------- ----------
30-May-2016 - 05-Jun-2016                            0          0          0
06-Jun-2016 - 12-Jun-2016                            0          0          0
13-Jun-2016 - 19-Jun-2016                         1000        100        200
20-Jun-2016 - 26-Jun-2016                         1500        150        300
27-Jun-2016 - 03-Jul-2016                         1100        110        130