ORACLE Group按周,月和年查询

时间:2011-11-08 19:24:57

标签: sql oracle group-by

我有一堆查询带有时间戳的数据,并根据最近几周,几个月和一年的时间吐出SUMS。看起来像这样

Week1    Sum for most recent week
Week2    Sum for second most recent week
WeekN    Sum for N most recent week
Jan-Dec  Sum for January-December
YTD      Sum for everything this year

这是查询当前执行此操作的方式

SELECT TIME_PERIOD, INDEX, SUM(ITEM)   
FROM (SELECT
        INDEX ,
        (CASE  
            WHEN ACTIVITY_DAY>=(TO_DATE( :end_day,
            'yyyy-mm-dd' )-6)  
            AND ACTIVITY_DAY<=(TO_DATE( :end_day,
            'yyyy-mm-dd' )-0) THEN 'WEEK1'  
            WHEN ACTIVITY_DAY>=(TO_DATE( :end_day,
            'yyyy-mm-dd' )-13)  
            AND ACTIVITY_DAY<=(TO_DATE( :end_day,
            'yyyy-mm-dd' )-7) THEN 'WEEK2'  
            ELSE NULL  
        END) AS TIME_PERIOD,
        MAX(ITEMS) AS ITEM
    FROM
        SOURCE  
    GROUP BY
        INDEX ,
        DAY  
    UNION
    ALL SELECT
        INDEX ,
        (CASE  
            WHEN ACTIVITY_DAY>=TO_DATE( :year||'-01-01',
            'yyyy-mm-dd' )  
            AND ACTIVITY_DAY<=TO_DATE( :year||'-01-31',
            'yyyy-mm-dd' ) THEN 'Jan'  
            WHEN ACTIVITY_DAY>=TO_DATE( :year||'-02-01',
            'yyyy-mm-dd' )  
            AND ACTIVITY_DAY<TO_DATE( :year||'-03-01',
            'yyyy-mm-dd' ) THEN 'Feb'   
            ELSE NULL  
        END) AS TIME_PERIOD ,
        MAX(ITEMS) AS ITEM
    FROM
        SOURCE  
    GROUP BY
        INDEX ,
        DAY  
    UNION
    ALL SELECT
        INDEX ,
        (CASE  
            WHEN ACTIVITY_DAY>=TO_DATE( :year||'-01-01',
            'yyyy-mm-dd' )  
            AND ACTIVITY_DAY<=TO_DATE( :end_day,
            'yyyy-mm-dd' ) THEN 'YTD'  
            ELSE NULL  
        END) AS TIME_PERIOD,
        MAX(ITEMS) AS ITEM
    FROM
        SOURCE  
    GROUP BY
        INDEX ,
        DAY)
GROUP BY INDEX, TIME_PERIOD  

Oracle中有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

我认为你正在寻找这样的东西:

with data as
(
    select sysdate - floor(dbms_random.value(1,400)) dt, floor(dbms_random.value(1,100)) val
    from dual
    connect by level <= 100
)
select
    time_period,
    sum(val) period_sum
from
(
    select -- weeks
        'Week'||(to_char(sysdate, 'WW') - to_char(dt, 'WW') + 1) time_period,
        val,
        (to_char(sysdate, 'WW') - to_char(dt, 'WW') + 1) ord
    from data
    where dt >= trunc(sysdate,'YY')
    union all
    select -- months
        to_char(dt, 'Mon') time_period,
        val,
        100+to_char(dt,'MM') ord
    from data
    where dt >= trunc(sysdate,'YY')
    union all
    select -- months
        'YTD' time_period,
        val,
        200
    from data
    where dt >= trunc(sysdate,'YY')
)
group by
    time_period, ord
order by
    ord;

请注意,您不需要WITH块,我只是用它来创建一些虚拟数据。 Ord列对您来说可能是不必要的,我只是用它来以逻辑方式对数据进行排序。