2016-08-05 51 views
0

我有一個日期時間表和倍數屬性,其中我分組了一些我彙總的一些表格,查詢將類似於上週爲每個客戶獲得的收入。 現在我想查看所請求的時間段和前一個時間段之間的更改,以便我將獲得2列收入和previous_revenue。取決於其他字段的彙總值

現在,我正在請求所需時間段的行加上前一個週期的行,對於每個聚合字段,我添加一個case語句,其中返回值或0,如果不在我想要的時間段內。

這會導致與聚合字段一樣多的CASE,但始終使用相同的條件語句。

我不知道是否有這個用例更好的設計...

SELECT 
customer, 
SUM(
    CASE TIMESTAMP_CMP('2016-07-01 00:00:00', ft.date) > 0 WHEN true THEN 
    REVENUE 
    ELSE 0 END 
) AS revenue, 
SUM(
    CASE TIMESTAMP_CMP('2016-07-01 00:00:00', ft.date) < 0 WHEN true THEN 
    REVENUE 
    ELSE 0 END 
) AS previous_revenue 

WHERE date_hour >= '2016-06-01 00:00:00' 
AND date_hour <= '2016-07-31 23:59:59' 
GROUP BY customer 

(在我的實際使用情況下,我有很多列,這使得它更加難看)

回答

0

第一,我建議重構時間戳並預先計算當前和以前的時間段以備後用。這並非絕對必要解決你的問題,但:

create temporary table _period as 
    select 
     '2016-07-01 00:00:00'::timestamp as curr_period_start 
     , '2016-07-31 23:59:59'::timestamp as curr_period_end 
     , '2016-06-01 00:00:00'::timestamp as prev_period_start 
     , '2016-06-30 23:59:59'::timestamp as prev_period_end 
; 

現在可能的設計,以避免時間戳的重複和CASE聲明是由段組第一,然後做一個FULL OUTER JOIN該表本身:

with _aggregate as (
    select 
     case 
      when date_hour between prev_period_start and prev_period_end then 'previous' 
      when date_hour between curr_period_start and curr_period_end then 'current' 
     end::varchar(20) as period 
     , customer 
    -- < other columns to group by go here > 
     , sum(revenue)  as revenue 
    -- < other aggregates go here > 
    from 
     _revenue, _period 
    where 
     date_hour between prev_period_start and curr_period_end 
    group by 1, 2 
) 
select 
    customer 
    , current_period.revenue as revenue 
    , previous_period.revenue as previous_revenue 
from 
       (select * from _aggregate where period = 'previous') previous_period 
full outer join (select * from _aggregate where period = 'current') current_period 

using(customer) -- All columns which have been group by must go into the using() clause: 
       -- e.g. using(customer, some_column, another_column) 
;