Redshift SQL:基于另一列的行间计算

时间:2017-04-26 21:39:26

标签: sql amazon-redshift

我正在Redshift中构建一个表作为Bowling Chart的基础。

我的数据格式为:

data

month   | product_id  | kpi_type  | values
april   |     1       | current   | 330
april   |     1       | target    | 300
april   |     2       | current   | 340
april   |     2       | target    | 300
march   |     2       | current   | 270
march   |     2       | target    | 300

我想在kpi_type = diff

中插入diff = current-target

我希望得到这个:

month   | product_id  | kpi_type  | values
april   |     1       | current   | 330
april   |     1       | target    | 300
april   |     1       | diff      | 30
april   |     2       | current   | 340
april   |     2       | target    | 300
april   |     2       | diff      | 40
march   |     2       | current   | 270
march   |     2       | target    | 300
march   |     2       | diff      | -30

我知道如何通过计算CTE中的差异然后将其与原始表联合来实现目标。但是我希望在很多不同的values和更复杂的方差公式上做到这一点,所以我正在寻找更有效的解决方案。

我在哪里:


    select
        a.month,
        a.product_id,   
        a.values as current,
        b.target,
        a.values - b.target as diff
    from data a
    left join
        (
            select
            month,
            product_id,
            values as target
            from data
            where kpi_type = 'target'
        ) b
    on md5(a.month || a.product_id) = md5(b.month || b.product_id)
    where kpi_type = 'current'
    group by 1,2,3

从那里我可以将它联合回data并获得所需的结果,但它看起来效率不高。

Close to this question on SQL Server

2 个答案:

答案 0 :(得分:1)

假设每月只有一个值,即kpi_types current和target的product_id,您可以聚合以获取diff行,并使用union all将其与原始结果组合。

select month,product_id,kpi_type,values from data
union all
select month,product_id,'diff' as kpi_type,   
coalesce(max(case when kpi_type='current' then values end),0) - 
coalesce(max(case when kpi_type='target' then values end),0) as values
from data 
group by month,product_id

答案 1 :(得分:0)

我无法使用评论功能。所以我会在这里写。我认为除了使用union在redshift中转置数据之外别无他法。因此,您可以使用窗口函数进行减法,而不是使用左连接查询来获取差异。

 sum(values)
    OVER (
      PARTITION BY month, product_id ) AS diff

首先,您可以在子查询中执行类似的操作:

    SELECT
       CASE WHEN type = 'target'
         THEN values * -1
       ELSE values END AS values
     FROM data

然后你可以结合它。