2016-10-04 79 views
-1

我的表值一樣......sqHow如何根據兩個日期獲得每週總和值?

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 

回答

0

下面的查詢在第一個分解子查詢中有輸入日期(從和到)。這些可以被製作成綁定變量,或者你想用來將這些輸入傳遞給查詢的任何機制。然後我在第二個分解子查詢中有測試數據;你最終的解決方案中並不需要這些。我在「周」因子查詢中創建了所有需要的星期,並使用左外連接,因此沒有事務的周將顯示0個和。請注意,在主查詢中,在我執行連接的情況下,基表中的「日期」列未包含在任何類型的函數中;這允許在該列上使用索引,如果該表非常大,您應該擁有這個索引,或者如果性能可能成爲其他任何原因的擔憂。請注意,輸出與您的不同(缺少最後一行),因爲我在表格中的最後一行之前輸入to-date。這是故意的,我想確保查詢正常工作。另外:我沒有使用「日期」或「星期」作爲列名;這是一個非常糟糕的做法。保留的Oracle關鍵字不應該用作列名。我用「dt」和「wk」代替。

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 
+0

@Mathuguy謝謝你的工作。 – Velu

1

您可以通過一個case語句實現這一目標:

例如

-- 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'); 
+0

@弗蘭克感謝您的答覆。兩個日期的意思是假設我在'02 -Jan-2016'和'30 -Dec-2016'之間給出它應該返回所有星期一到星期日的總和值 – Velu

+1

在這種情況下,簡單地按照TRUNC(a_date,'iw')|| ' - ' || TRUNC(a_date + 7,'iw')' –

0

你可以試試下面的一樣,我選擇了13軍-2016爲起始日期。您可以根據您的要求選擇任意日期範圍。

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;