计算两行之间的百分比变化到 Postgres 中的视图
Calculate the percentage change between two rows into a view in Postgres
我有一个 table,其中包含 200 多个国家/地区的年度值。对于图形表示,我想获得两个特定年份(1990 年和 2013 年)之间的百分比变化。
table 看起来有点像这样:
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
每个国家。
它可能会变得更复杂,因为 table 中有多个变量(由附加列表示),需要通过这些附加列值进行过滤,例如 id_source = 1
或 id_source = 2
,或id_sector = 1
或id_sector = 2
。
非常感谢任何帮助!
一种方式,可能最快:
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 中引入的:
- How can I simplify this game statistics query?
在旧版本中,您可以用 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 = ) * 100)
/ NULLIF(sum(t.value) FILTER (WHERE year = ), 0) AS pct
FROM tbl t
WHERE t.year IN (, )
AND t.id_source = 1 -- ??
GROUP BY t.id_country
-- ORDER BY ???
$func$ LANGUAGE sql STABLE;
致电:
SELECT * FROM f_pct_calc(1990, 2013);
我有一个 table,其中包含 200 多个国家/地区的年度值。对于图形表示,我想获得两个特定年份(1990 年和 2013 年)之间的百分比变化。
table 看起来有点像这样:
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
每个国家。
它可能会变得更复杂,因为 table 中有多个变量(由附加列表示),需要通过这些附加列值进行过滤,例如 id_source = 1
或 id_source = 2
,或id_sector = 1
或id_sector = 2
。
非常感谢任何帮助!
一种方式,可能最快:
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 中引入的:
- How can I simplify this game statistics query?
在旧版本中,您可以用 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 = ) * 100)
/ NULLIF(sum(t.value) FILTER (WHERE year = ), 0) AS pct
FROM tbl t
WHERE t.year IN (, )
AND t.id_source = 1 -- ??
GROUP BY t.id_country
-- ORDER BY ???
$func$ LANGUAGE sql STABLE;
致电:
SELECT * FROM f_pct_calc(1990, 2013);