2010-11-26 29 views
3

我試圖建立一個基於日期時間範圍的交易報告,對於可以在兩天內開放的業務,取決於班次管理。如何在DATETIME範圍內「分組」?

用戶可以選擇一個日期時間範圍(每月,每天,每週,免費...),我執行的查詢獲取startDateTime和EndDateTime,並將返回按天分組的所有交易。

I.E.

DateTime  Total Sales 
--------------------------- 
10/15/2010  $2,300.38 
10/16/2010  $1,780.00 
10/17/2010  $4,200.22 
10/20/2010  $900.66 

我的問題是,如果企業的轉變是設置好的,例如,從上午5點00分至上午02點,第二天,從午夜做到上午02時的所有交易將在第二天進行分組...等等...總數已損壞。 當一個企業有這樣的轉變,它希望基於這種轉變的報告,但沒有代碼修補(我使用Java調用Oracle本機查詢),我無法得到所需的報告。

我想知道是否有一些聰明的方式,由日期時間範圍分組這些事務使用無非是甲骨文。

這裏去查詢,以7月的月份:

SELECT Q1.dateFormat, NVL(Q1.sales, 0) 
    FROM (
     SELECT to_date(to_char(tx.datetimeGMT +1/24 , 'mm-dd-yyyy'), 'mm-dd-yyyy') AS dateFormat      
       , NVL(SUM(tx.amount),0) AS sales 
      FROM Transaction tx 
      WHERE tx.datetimeGMT > to_date('20100801 08:59:59', 'yyyymmdd hh24:mi:ss') +1/24 
       AND tx.datetimeGMT < to_date('20100901 09:00:00', 'yyyymmdd hh24:mi:ss') + 1/24 
      GROUP BY to_date(to_char(tx.datetimeGMT +1/24 , 'mm-dd-yyyy'), 'mm-dd-yyyy') 
    ) Q1 
    ORDER BY 1 DESC 

回答

3

謝謝大家的答案,通過採取看看他們,我可以寫向下查詢我正在搜索:

SELECT CASE 
    WHEN EXTRACT(HOUR FROM TX.DATETIME) >= 5 THEN TO_CHAR(TX.DATETIME,'DD-MM-YYYY') 
    WHEN EXTRACT(HOUR FROM TX.DATETIME) BETWEEN 0 AND 2 THEN TO_CHAR(TX.DATETIME-1,'DD-MM-YYYY') 
    WHEN EXTRACT(hour from tx.datetime) between 2 and 5 THEN to_char(TX.DATETIME-1,'DD-MM-YYYY') 
    END AS age, 
    NVL(SUM(tx.amount),0) AS sales 
FROM TRANSACTION TX 
WHERE tx.datetime > to_date('20100801 08:59:59', 'yyyymmdd hh24:mi:ss') 
    AND TX.DATETIME < TO_DATE('20100901 09:00:00', 'yyyymmdd hh24:mi:ss') 
GROUP BY CASE 
    WHEN EXTRACT(HOUR FROM TX.DATETIME) >= 5 THEN TO_CHAR(TX.DATETIME,'DD-MM-YYYY') 
    WHEN EXTRACT(HOUR FROM TX.DATETIME) BETWEEN 0 AND 2 THEN TO_CHAR(TX.DATETIME-1,'DD-MM-YYYY') 
    WHEN EXTRACT(hour from tx.datetime) between 2 and 5 THEN to_char(TX.DATETIME-1,'DD-MM-YYYY') 
    END 
ORDER BY 1 
0

要按日期範圍組,你必須有這個範圍內成列的值到子查詢,並通過其組在你的查詢中。顯然,此列值中的此日期範圍將爲VARCHAR類型。

+0

它不一定是一個varchar值。 – Donnie 2010-11-26 16:26:18

0

如果當天的第一班從08:00開始,並且當天的最後一班在第二天07:59結束,則可以使用類似的方式按班次日期對事務進行分組。

select trunc(trans_date - interval '8' hour) as shift_date 
     ,sum(amount) 
    from transactions 
group 
    by trunc(trans_date - interval '8' hour) 
order 
    by shift_date desc; 
0

你可以試試這個方法(只是從我的頭,甚至不知道它運行):

select 
trans_date, 
trans_shift, 
aggregates(whatever) 
from (
    select 
    -- we want to group by normalized transaction date, 
    -- not by real transaction date 
    normalized_trans_date, 
    -- get the shift to group by 
    case 
     when trans_date between trunc(normalized_trans_date) + shift_1_start_offset and 
           trunc(normalized_trans_date) + shift_1_end_offset then 
     1 
     when trans_date between trunc(normalized_trans_date) + shift_2_start_offset and 
           trunc(normalized_trans_date) + shift_2_end_offset then 
     2 
     ... 
     when trans_date between trunc(normalized_trans_date) + shift_N_start_offset and 
           trunc(normalized_trans_date) + shift_N_end_offset then 
     N 
    end trans_shift, 
    whatever 
    from (
     select 
     -- get a normalized transaction date: if date is before 1st shift 
     -- it belongs to the day before 
     case 
      when trans_date - trunc(trans_date) < shift_1_start_offset then 
      trans_date - 1 
      else 
      trans_date 
     end normalized_trans_date, 
     t.* 
     from 
     transactions t 
    ) 
) 
group by trans_date, trans_shift