如何在DATETIME范围内“分组”?

时间:2010-11-26 14:44:52

标签: oracle datetime group-by range

我正在尝试建立一个基于日期时间范围的交易报告,用于可以在两天内开放的业务,具体取决于轮班管理。

用户可以选择日期时间范围(每月,每天,每周,自由......),我实施的查询获取startDateTime和EndDateTime,并将返回按日分组的所有事务。

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

我的问题是,如果设置了业务的转移,例如,从第二天的05.00 AM到02.00 AM,从午夜到凌晨02.00完成的所有交易将在第二天进行分组......等等......总数已损坏。 当一个企业发生这样的转变时,它需要一个基于该转变的报告,但没有代码修补(我使用Java调用Oracle本机查询),我无法获得所请求的报告。

我想知道是否有一些聪明的方式可以使用日期时间范围对这些事务组进行分组。

以下是七月份的查询:

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

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

要按日期范围进行分组,您必须将此范围放入子查询中的列值,并在查询中按其分组。显然,此列值中的此日期范围将为VARCHAR类型。

答案 2 :(得分: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;

答案 3 :(得分: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

答案 4 :(得分:0)

带有 trunc(trans_date - interval '8' hours) 的 Ronnis 解决方案帮助我进行了类似的查询。 做了一份备份报告,并且必须总结来自 RC_BACKUP_SET_DETAILS 的输出字节。备份任务运行时间超过 8 小时,一个作业有几个 RC_BACKUP_SET_DETAILS 行,从晚上开始到第二天结束。

select  trunc(start_time - interval '12' hour) "Start Date",
   to_char(sum(output_bytes)/(1024*1024*1024),'999,990.0') "Output GB" 
   from rc_backup_set_details  
   where db_key = 173916 and backup_type = 'I' and incremental_level = 0 
   group by trunc(start_time - interval '12' hour) 
   order by 1 asc;