redshift / postgresql - case语句中以前选择的列

时间:2017-02-08 23:18:29

标签: postgresql amazon-redshift

我有一个sql查询,它基本上查询包含两列的表:event_name和event_count。

event_count是一个整数,表示事件执行的秒数。我编写了下面的查询,将事件汇总到层,即1-5秒,5-10秒等,这样我们就可以确定每个执行的时间。

我想知道是否有更好的方法去做我在下面做的事情,因为我不认为这是目前非常优化的,因为它必须在每个案例中运行sum()。

我尝试将之前选择的列(d_event_count)放在case语句中,如下所示:

(CASE WHEN d_event_count >= 0 and d_event_count < 5 THEN d_event_count ELSE 0 END) as d_time_1_5,

但它失败,表明表中不存在列,所以我在这里寻求帮助:)

select
    event_name as d_event_name,
    sum(event_count) as d_event_count,

    (CASE WHEN sum(event_count) >= 0 and sum(event_count) < 5 THEN sum(event_count) ELSE 0 END) as d_time_1_5,
    (CASE WHEN sum(event_count) >= 5 and sum(event_count) < 10 THEN sum(event_count) ELSE 0 END) as d_time_5_10,
    (CASE WHEN sum(event_count) >= 10 and sum(event_count) < 15 THEN sum(event_count) ELSE 0 END) as d_time_10_15,
    (CASE WHEN sum(event_count) >= 15 and sum(event_count) < 30 THEN sum(event_count) ELSE 0 END) as d_time_15_30,
    (CASE WHEN sum(event_count) >= 30 and sum(event_count) < 45 THEN sum(event_count) ELSE 0 END) as d_time_30_45,
    (CASE WHEN sum(event_count) >= 45 and sum(event_count) < 60 THEN sum(event_count) ELSE 0 END) as d_time_45_60,
    (CASE WHEN sum(event_count) >= 60 and sum(event_count) < 120 THEN sum(event_count) ELSE 0 END) as d_time_60_120,
    (CASE WHEN sum(event_count) >= 120 and sum(event_count) < 180 THEN sum(event_count) ELSE 0 END) as d_time_120_180,
    (CASE WHEN sum(event_count) >= 180 and sum(event_count) < 240 THEN sum(event_count) ELSE 0 END) as d_time_180_240,
    (CASE WHEN sum(event_count) >= 240 and sum(event_count) < 300 THEN sum(event_count) ELSE 0 END) as d_time_240_300,
    (CASE WHEN sum(event_count) >= 300 THEN sum(event_count) ELSE 0 END) as d_time_300

from
    product_events
where
   ...
group by 1

不可能更改表结构,还有许多其他列,这只是一个精简表示。

有人能帮助我吗?

1 个答案:

答案 0 :(得分:0)

尝试这种方式,它使用d_event_count的累积和:

create temp table ev as
select *
from ( 
values 
('event 1'::text, 5::int),
('event 2'::text, 5::int),
('event 3'::text, 5::int),
('event 4'::text, 5::int),
('event 5'::text, 5::int),
('event 6'::text, 5::int),
('event 7'::text, 5::int),
('event 8'::text, 5::int),
('event 9'::text, 5::int)
) t (event_name, d_event_count);

with sm as
(
select event_name, sum(d_event_count) over (order by event_name) as total
from ev
)
select event_name, total,
       case when total between 0 and 5 then 'd_time_1_5'
            when total between 6 and 10 then 'd_time_6_10'
            when total between 11 and 15 then 'd_time_11_15'
            else 'more than 15'
       end as d_name
from sm;

+------------+-------+--------------+
| event_name | total | d_name       |
+------------+-------+--------------+
| event 1    | 5     | d_time_1_5   |
+------------+-------+--------------+
| event 2    | 10    | d_time_6_10  |
+------------+-------+--------------+
| event 3    | 15    | d_time_11_15 |
+------------+-------+--------------+
| event 4    | 20    | more than 15 |
+------------+-------+--------------+
| event 5    | 25    | more than 15 |
+------------+-------+--------------+
| event 6    | 30    | more than 15 |
+------------+-------+--------------+
| event 7    | 35    | more than 15 |
+------------+-------+--------------+
| event 8    | 40    | more than 15 |
+------------+-------+--------------+
| event 9    | 45    | more than 15 |
+------------+-------+--------------+

使用WINDOW函数的另一种解决方案:

select event_name, sum(d_event_count) over w1 as total,
       case when sum(d_event_count) over w1 between 0 and 5 then 'd_time_1_5'
            when sum(d_event_count) over w1 between 6 and 10 then 'd_time_6_10'
            when sum(d_event_count) over w1 between 11 and 15 then 'd_time_11_15'
            else 'more than 15'
       end as d_name
from ev
WINDOW w1 AS (order by event_name);

在此处查看:http://rextester.com/BTR25807