【问题标题】:Calculate the percentage change between two rows into a view in Postgres计算两行之间的百分比变化到 Postgres 中的视图中
【发布时间】:2017-03-13 11:26:30
【问题描述】:

我有一张表格,其中包含 200 多个国家/地区的年度值。对于图形表示,我想获得 1990 年和 2013 年两个特定年份之间的百分比变化。

表格看起来有点像这样:

  id_country       year       value
    886            2002      161.348
    886            2003      161.348
    886            2004      176.016
    886            2005      176.016
    886            2006      179.683
    886            2007      183.35
    886            2008      201.685
    886            2009      227.354
    886            2010      234.688
    886            2011      245.689
    886            2012      293.36
    886            2013      440.04
    620            1990      40.337
    620            1991      1056.096
    620            1992      1151.438
    620            1993      1389.793
    620            1994      1584.144
    620            1995      1631.815
    620            1996      1749.159
    620            1997      1796.83
    620            1998      1906.84
    620            1999      1664.818
    620            2000      1642.816
    620            2001      2016.85
    620            2002      1760.16
    620            2003      1873.837
    620            2004      1961.845
    620            2005      2310.21
    620            2006      2328.545
    620            2007      2361.548
    620            2008      3329.636
    620            2009      3069.279
    620            2010      3098.615
    620            2011      2823.59
    620            2012      3373.64
    620            2013      2948.268

我认为最好的方法是使用 id_country 生成一个 VIEW,它会计算差异。但我不知道那个查询会是什么样子。它必须SELECT 所有国家/地区,然后将year = 2013 除以year = 1990 对于每个国家/地区。

它可能会变得更复杂,因为该表中有多个变量(由附加列表示),需要通过这些附加列值过滤这些变量,例如 id_source = 1id_source = 2id_sector = 1id_sector = 2.

非常感谢任何帮助!

【问题讨论】:

    标签: sql postgresql percentage difference


    【解决方案1】:

    一种方式,可能是最快的:

    CREATE VIEW pct_2013_1990 AS
    SELECT id_country
         ,       (sum(value) FILTER (WHERE year = 2013) * 100)
         / NULLIF(sum(value) FILTER (WHERE year = 1990), 0) AS pct
    FROM   tbl
    WHERE  year IN (1990, 2013)
    AND    id_source = 1 -- ??
    GROUP  BY id_country
    -- ORDER BY ???
    

    这假设您在 1990 年对于 每个 国家/地区的值 > 0,否则您将得到除以零。在示例中,我使用NULLIF 对此进行了辩护。在这种情况下,结果为 NULL。

    pct 是 2013 年值与 1990 年相比的百分比。要获得 百分比变化,您可以从中减去 100。不确定您到底需要什么。

    您可以使用round() 来减少小数位数。

    聚合 FILTER 子句是在 Postgres 9.4 中引入的:

    在旧版本中,您可以用 CASE 表达式替换。

    您可以改为使用集合返回函数并将年份参数化以使其适用于任何年份。

    CREATE FUNCTION f_pct_calc(year1 integer, year2 integer)
      RETURNS TABLE(id_country int, pct numeric) AS
    $func$ 
        SELECT t.id_country
             ,       (sum(t.value) FILTER (WHERE year = $2) * 100)
             / NULLIF(sum(t.value) FILTER (WHERE year = $1), 0) AS pct
        FROM   tbl t
        WHERE  t.year IN ($1, $2)
        AND    t.id_source = 1 -- ??
        GROUP  BY t.id_country
        -- ORDER BY ???
    $func$ LANGUAGE sql STABLE;
    

    呼叫:

    SELECT * FROM f_pct_calc(1990, 2013);
    

    【讨论】:

    • 哇,酷!非常感谢。小修正:在FILTER 子句中,应该是FILTER (WHERE year = 2013)(不是country)。
    • @luftikus143:谢谢,已修复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多