处理CASE语句中的重叠条件

时间:2014-02-27 23:38:09

标签: sql vertica vsql

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

结果实际上似乎给了我第1-3天,第4-10天和第11-30天的时段。我相信这是因为存在重叠条件,并且只要满足第一个条件,SQL就会停止处理CASE语句。

我想要的是每个桶的总数(即3天总和,10天总和和30天总和)。

有没有办法在不添加其他字段的情况下执行此操作?

PS - 语法与传统的sql有点不同,因为它是vsql(vertica)。

4 个答案:

答案 0 :(得分:1)

制作三个总计而不是一个总数,并使用条件来确定每个记录的计数位置,而不是尝试确定单个总计的期间:

select
  sum(case when ymd between CURRENT_DATE - 4 and CURRENT_DATE - 1 then cost else 0 end) as '3day total',
  sum(case when ymd BETWEEN CURRENT_DATE - 11 and CURRENT_DATE - 5 then cost else 0 end) as '10day total',
  sum(case when ymd BETWEEN CURRENT_DATE - 31 and CURRENT_DATE - 12 then cost else 0 end) as '30day total'
from
  table
and
  ymd between CURRENT_DATE -31 and CURRENT_DATE -1
group by
  1

注意:我不确定您想要在哪个日期范围内计算,因此我将它们设置为不重叠,因为如果您使用between,这是最有意义的。如果您仍然希望它们重叠,那么您只需进行比较,而不是使用between,因为已经过滤了CURRENT_DATE - 1之后的任何值。

编辑:

要在行中获得结果,可以在选择之间建立联合:

select '3day total' as period, sum(cost) as cost
from table
where ymd between CURRENT_DATE - 4 and CURRENT_DATE - 1
union all
select '10day total', sum(cost)
from table
where ymd BETWEEN CURRENT_DATE - 11 and CURRENT_DATE - 5
union all
select '30day total', sum(cost)
from table
where ymd BETWEEN CURRENT_DATE - 31 and CURRENT_DATE - 12

答案 1 :(得分:0)

尝试为每个存储桶设置不同的字段。我假设您想要计算每个存储桶的成本,如果要对不同的字段求和,则可能需要更改THEN cost

您在查询中也缺少WHERE子句。条件以AND语句开头,您可能想要更正此问题。

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

答案 2 :(得分:0)

尝试扭转您的状况:

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

答案 3 :(得分:0)

如果您希望将其保留为包含一列的三行,则可采用以下方法:

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;

编辑:

cross join的工作原理是为原始表中的每一行创建三行。每个组都考虑了这些行中的每一行 - 因此重叠不是问题。这些组由其名称和diff值定义。

换句话说,如果数据以7天前的一行开头:

ymd                  cost
CURRENT_DATE - 7      $10

然后这会被cross join

乘以3
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

然后,当这些由which汇总时,会计算出正确的值:

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