2014-03-06 130 views
1

我创建了结构和样本数据here。我不知道如何计算随时间推移的变化。计算随时间变化的百分比

我想要的结果集为:

a | % growth 
abc | 4.16 
def | 0.83 
hig | -0.2 

的百分比变化为(最后一个值 - 第一个值)/天:

a | % growth 
abc | (30-5)/6 
def | (6-1)/6 
hig | (4-5)/5 

我想:

SELECT a.*, 
     b.val, 
     c.val 
FROM (SELECT a, 
       Min(dt) AS lowerDt, 
       Max(dt) AS upperDt 
     FROM tt 
     GROUP BY a) a 
     LEFT JOIN tt b 
       ON b.dt = a.lowerdt 
       AND b.a = a.a 
     LEFT JOIN tt c 
       ON c.dt = a.upperdt 
       AND b.a = a.a 

如果可能的话,我想避免CTE。

+0

为什么你要避免使用CTE?在许多情况下,它们使代码更容易阅读。 – MatBailie

+1

也许为了可能的移植到MySQL? – ely

+0

@MatBailie到其他DBMS(不是MySQL)的可移植性 – user3242205

回答

1

你不想要minmax,你真的想要firstlast

我这样做的一种方法是使用ROW_NUMBER()来告诉我从开始或结束的位置。然后使用MAX(CASE WHEN pos=1 THEN x ELSE null END)来获得我想要的值。

SELECT 
    a, 
    MAX(CASE WHEN pos_from_first = 1 THEN dt ELSE NULL END) AS first_date, 
    MAX(CASE WHEN pos_from_final = 1 THEN dt ELSE NULL END) AS final_date, 
    MAX(CASE WHEN pos_from_first = 1 THEN val ELSE NULL END) AS first_value, 
    MAX(CASE WHEN pos_from_final = 1 THEN val ELSE NULL END) AS final_value, 
    100 
    * 
    CAST(MAX(CASE WHEN pos_from_final = 1 THEN val ELSE NULL END) AS DECIMAL(9,6)) 
/
    CAST(MAX(CASE WHEN pos_from_first = 1 THEN val ELSE NULL END) AS DECIMAL(9,6)) 
    - 
    100              AS perc_change 
FROM 
(
    SELECT 
    ROW_NUMBER() OVER (PARTITION BY a ORDER BY dt ASC) AS pos_from_first, 
    ROW_NUMBER() OVER (PARTITION BY a ORDER BY dt DESC) AS pos_from_final, 
    * 
    FROM 
    tt 
) 
    AS ordered 
GROUP BY 
    a 

http://sqlfiddle.com/#!6/ad95d/11

+0

编辑将流氓'ASC'改为'DESC',修复百分比等 – MatBailie

+0

我在测试时注意到窗口中的排序。 – user3242205