用SQL计算两年之间的人口差异?

时间:2019-07-11 00:24:29

标签: sql

我想知道如何使用SQL计算两年人口的差异。该表包含三列:国家,年份和人口。有关更多信息,您可以从以下链接中查看问题8:https://www.codecademy.com/practice/projects/world-populations-sql-practice

我尝试了以下代码,但是第一个代码需要手动计算,而另一个代码则无效。

SELECT population, year FROM population_years
WHERE country = 'Indonesia' AND year = 2000 
OR country = 'Indonesia' AND year = 2010;

SELECT 
(SELECT population, year FROM population_years
WHERE country = 'Indonesia' AND year = 2000) -
(SELECT population, year FROM population_years
WHERE country = 'Indonesia' AND year = 2010)

2010年和2000年印度尼西亚的人口分别为2.42亿和2.14亿。

那么我该怎么写查询才能返回28M?

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以将2000条记录和2010条记录一起添加:

SELECT p10.population - p00.population
FROM population_years p00
    JOIN  population_years p10 ON p10.country = p00.country 
                              AND p10.year = 2010
WHERE p00.country = 'Indonesia' 
  AND p00.year = 2000

答案 1 :(得分:0)

如果您使用的是Transact-SQL,则可以使用LAG()函数:

SELECT X.MIN_YR_POP, X.MAX_YR_POP, X.NET_POP_VALUE
FROM (
    SELECT PY.population AS [MAX_YR_POP], LAG(PY.population, 10, NULL) OVER(ORDER BY PY.year) AS [MIN_YR_POP]
    ,   CONVERT(FLOAT, PY.population) - CONVERT(FLOAT, LAG(PY.population, 10, NULL) OVER(ORDER BY PY.year)) AS [NET_POP_VALUE]
    FROM #_pop_yrs AS PY
) AS X
WHERE X.MIN_YR_POP IS NOT NULL

输出:

MAX_YR_POP  MIN_YR_POP  NET_POP_VALUE
242.96834   214.67661   28.29173

LAG()函数采用标量值,偏移值和默认值(如果无效或超出范围),然后返回已对齐所需值的表。对于上面的子查询,滞后时间为10,输出看起来像这样:

year    MAX_YR_POP  MIN_YR_POP  NET_POP_VALUE
2000    214.67661   NULL    NULL
2001    217.83628   NULL    NULL
2002    220.97191   NULL    NULL
2003    223.06967   NULL    NULL
2004    226.00413   NULL    NULL
2005    228.89575   NULL    NULL
2006    231.82024   NULL    NULL
2007    234.694     NULL    NULL
2008    237.51236   NULL    NULL
2009    240.27152   NULL    NULL
2010    242.96834   214.67661   28.29173

您会得到很多不希望有的结果,因此我们创建了一个子查询并接受了我们想要的内容。

请注意,对于LAG(),您不能使用负偏移值;我们无法使用-10来回顾10行。相反,您必须知道表的顺序并相应地进行调整。如果我们想扭转结果,则我们的年度价值可能会下降:

OVER(ORDER BY PY.year DESC)

此更新的查询:

SELECT PY.population AS [MAX_YR_POP], LAG(PY.population, 10, NULL) OVER(ORDER BY PY.year DESC) AS [MIN_YR_POP]
,   CONVERT(FLOAT, PY.population) - CONVERT(FLOAT, LAG(PY.population, 10, NULL) OVER(ORDER BY PY.year DESC)) AS [NET_POP_VALUE]
FROM #_pop_yrs AS PY

将返回此:

year    MAX_YR_POP  MIN_YR_POP  NET_POP_VALUE
2010    242.96834   NULL    NULL
2009    240.27152   NULL    NULL
2008    237.51236   NULL    NULL
2007    234.694     NULL    NULL
2006    231.82024   NULL    NULL
2005    228.89575   NULL    NULL
2004    226.00413   NULL    NULL
2003    223.06967   NULL    NULL
2002    220.97191   NULL    NULL
2001    217.83628   NULL    NULL
2000    214.67661   242.96834   -28.29173

我们的2010年人口价值现在位于顶部,而2000年的人口价值位于底部。不过,我们是宇宙的主人,因此我们可以将ORDER BY应用于整个查询并更正输出:

SELECT PY.year, PY.population AS [MAX_YR_POP], LAG(PY.population, 10, NULL) OVER(ORDER BY PY.year DESC) AS [MIN_YR_POP]
,   CONVERT(FLOAT, PY.population) - CONVERT(FLOAT, LAG(PY.population, 10, NULL) OVER(ORDER BY PY.year DESC)) AS [NET_POP_VALUE]
FROM #_pop_yrs AS PY
ORDER BY PY.year

并且:

year    MAX_YR_POP  MIN_YR_POP  NET_POP_VALUE
2000    214.67661   242.96834   -28.29173
2001    217.83628   NULL    NULL
2002    220.97191   NULL    NULL
2003    223.06967   NULL    NULL
2004    226.00413   NULL    NULL
2005    228.89575   NULL    NULL
2006    231.82024   NULL    NULL
2007    234.694     NULL    NULL
2008    237.51236   NULL    NULL
2009    240.27152   NULL    NULL
2010    242.96834   NULL    NULL

可能不是您所提问题的最佳解决方案,但在某些时候它可能适用于生产线!请注意,还有一个LEAD()函数可以预见许多行。

编辑:如果您有雄心壮志,并且想要在不使用CURSOR的情况下获取所有值,则可以迭代整个过程。这是一个示例,该示例在跳过任何空年份的同时几乎计算了所有组合。它可能需要一些调整。

DECLARE @_results TABLE (
      year1 CHAR(4),
      year2 CHAR(4),
      pop1 FLOAT,
      pop2 FLOAT,
      net_pop FLOAT
)

DECLARE @_count INT = 1
WHILE (@_count <= (SELECT COUNT(1) FROM #_pop_yrs))
    BEGIN
        INSERT INTO @_results
        SELECT X.[year1], X.[year2], X.[pop1], X.[pop2], ROUND(X.[net_pop], 5) AS [net_pop]
        FROM (
            SELECT PY.year AS [year1]
            ,   LAG(PY.year, @_count, NULL) OVER(ORDER BY PY.year) AS [year2]
            ,   PY.population AS [pop1]
            ,   LAG(PY.population, @_count, NULL) OVER(ORDER BY PY.year) AS [pop2]
            ,   CONVERT(FLOAT, PY.population) - CONVERT(FLOAT, LAG(PY.population, @_count, NULL) OVER(ORDER BY PY.year)) AS [net_pop]
            FROM #_pop_yrs AS PY
        ) AS X
        WHERE X.[year1] IS NOT NULL AND X.year2 IS NOT NULL
        SET @_count += 1
    END

SELECT *
FROM @_results
ORDER BY year1, year2

输出:

year1   year2   pop1        pop2        net_pop
2001    2000    217.83628   214.67661   3.15967
2002    2000    220.97191   214.67661   6.2953
2002    2001    220.97191   217.83628   3.13563
2003    2000    223.06967   214.67661   8.39306
2003    2001    223.06967   217.83628   5.23339
2003    2002    223.06967   220.97191   2.09776
2004    2000    226.00413   214.67661   11.32752
2004    2001    226.00413   217.83628   8.16785
2004    2002    226.00413   220.97191   5.03222
2004    2003    226.00413   223.06967   2.93446
2005    2000    228.89575   214.67661   14.21914
2005    2001    228.89575   217.83628   11.05947
2005    2002    228.89575   220.97191   7.92384
2005    2003    228.89575   223.06967   5.82608
2005    2004    228.89575   226.00413   2.89162
2006    2000    231.82024   214.67661   17.14363
2006    2001    231.82024   217.83628   13.98396
2006    2002    231.82024   220.97191   10.84833
2006    2003    231.82024   223.06967   8.75057
2006    2004    231.82024   226.00413   5.81611
2006    2005    231.82024   228.89575   2.92449
2007    2000    234.694     214.67661   20.01739
2007    2001    234.694     217.83628   16.85772
2007    2002    234.694     220.97191   13.72209
2007    2003    234.694     223.06967   11.62433
2007    2004    234.694     226.00413   8.68987
2007    2005    234.694     228.89575   5.79825
2007    2006    234.694     231.82024   2.87376
2008    2000    237.51236   214.67661   22.83575
2008    2001    237.51236   217.83628   19.67608
2008    2002    237.51236   220.97191   16.54045
2008    2003    237.51236   223.06967   14.44269
2008    2004    237.51236   226.00413   11.50823
2008    2005    237.51236   228.89575   8.61661
2008    2006    237.51236   231.82024   5.69212
2008    2007    237.51236   234.694     2.81836
2009    2000    240.27152   214.67661   25.59491
2009    2001    240.27152   217.83628   22.43524
2009    2002    240.27152   220.97191   19.29961
2009    2003    240.27152   223.06967   17.20185
2009    2004    240.27152   226.00413   14.26739
2009    2005    240.27152   228.89575   11.37577
2009    2006    240.27152   231.82024   8.45128
2009    2007    240.27152   234.694     5.57752
2009    2008    240.27152   237.51236   2.75916
2010    2000    242.96834   214.67661   28.29173
2010    2001    242.96834   217.83628   25.13206
2010    2002    242.96834   220.97191   21.99643
2010    2003    242.96834   223.06967   19.89867
2010    2004    242.96834   226.00413   16.96421
2010    2005    242.96834   228.89575   14.07259
2010    2006    242.96834   231.82024   11.1481
2010    2007    242.96834   234.694     8.27434
2010    2008    242.96834   237.51236   5.45598
2010    2009    242.96834   240.27152   2.69682