sqlverticavsql

Dealing with overlapping conditions in CASE statement


SELECT (CASE WHEN ymd BETWEEN CURRENT_DATE -4 AND CURRENT_DATE -1 THEN '3day total' 
WHEN ymd BETWEEN CURRENT_DATE -11 AND CURRENT_DATE -1 THEN '10day total' 
WHEN ymd BETWEEN CURRENT_DATE -31 AND CURRENT_DATE -1 THEN '30day total' END) AS 'Period',
SUM(cost) cost
FROM table
WHERE ymd BETWEEN CURRENT_DATE -31 AND CURRENT_DATE -1
GROUP BY 1

The result actually seems to give me Period buckets of days 1-3, days 4-10 and days 11-30. I believe this is because there are overlapping conditions and SQL stops processing the CASE statement as soon as the first condition is met.

What I want are the totals for each bucket (ie 3 day sum, 10 day sum and 30 day sum).

Is there a way to do this without adding additional fields?

PS - the syntax is a bit different then traditional sql because it's vsql (vertica).


Solution

  • If you want to keep this as three rows with one column, here is a way:

    SELECT which,
           sum(CASE WHEN ymd BETWEEN CURRENT_DATE - diff AND CURRENT_DATE -1 THEN cost
                    else 0
               end) as cost
    FROM table t cross join
         (select '3day total' as which, 4 as diff union all
          select '10day total', 11 union all
          select '30day total', 31
         ) w
    WHERE ymd BETWEEN CURRENT_DATE -31 AND CURRENT_DATE -1
    GROUP BY which;
    

    EDIT:

    The cross join works by creating three rows for each row in the original table. Each of these rows is considered for each group -- so overlaps are not an issue. The groups are defined by their name and the diff value.

    In other words, if the data started with one row that was 7 days ago:

    ymd                  cost
    CURRENT_DATE - 7      $10
    

    Then this gets multiplied into 3 by the cross join:

    which         diff       ymd                 cost
    3day total      4        CURRENT_DATE - 7     $10
    10day total    11        CURRENT_DATE - 7     $10
    30day total    31        CURRENT_DATE - 7     $10
    

    Then, when these are aggregated by which, the correct values are calculated:

    which         Total
    3day total      $0
    10day total    $10
    30day total    $10