如何使用这种模式编写可执行的postgreSQL以计算平均值和百分比?

时间:2019-04-06 20:06:45

标签: sql postgresql

我正在学习SQL(自学)。我正在尝试编写一个可执行的postgres SQL查询来回答此问题:根据原籍城市(名称),计算出付款的行程百分比 比该城市的出行平均要高出至少10%。

上下文:1)已完成的旅程被定义为在租金表中状态为“已完成”的旅程。 2)仅考虑最近30天的行程。

我从什么开始(希望看起来不错)

SELECT n.name, r.origin_id, SUM(r.fare_dollars), AVG(r.fare_dollars), count(r.id)
FROM rentals r, neighborhood n
LEFT JOIN r ON r.origin_id = n.id
GROUP BY n.name;

在正确的轨道上?!

我需要您的帮助(如果我对这种方法是正确的):

该问题将要求我执行一个子查询,该查询将拉出所有记录以查看其与平均票价的比较。然后,我需要编写另一个查询,告诉我哪些游乐设施比平均票价高出10%。

我期待看到您可能提供的任何见解!请让我知道是否可以提供其他信息。

谢谢。

1 个答案:

答案 0 :(得分:0)

您正在朝正确的方向思考,但是您的查询技能还没有,对吧?我将尽我所能进行解释,希望您能继续学习(如果不能,请随时提出。)

因此,首先,您需要知道每个出发地的平均票价是多少:

SELECT n.id, n.name, AVG(r.fare_dollars) AS average_fare
  FROM neighborhood n
  JOIN rentals r
    ON r.origin_id = n.id
 GROUP BY n.id, n.name

这是一个相当简单的查询,尽管通常在这里您不需要id。不过,我们将使用此查询与各个游乐设施进行比较,因此我们将其加入到我们的租金表中:

SELECT avg_per_neighborhood.name 
     , SUM(CASE 
            WHEN r.fare_dollars >= avg_per_neighborhood.average_fare * 1.1 THEN 1.0 
            ELSE 0 
          END) / COUNT(*) AS percAbove110
  FROM rentals r
  JOIN (SELECT n.id, n.name, AVG(r.fare_dollars) AS average_fare
          FROM neighborhood n
          JOIN rentals r
            ON r.origin_id = n.id
         GROUP BY n.id, n.name) avg_per_neighborhood
    ON r.origin_id = avg_per_neighborhood.id
 GROUP BY avg_per_neighborhood.name

有趣的部分当然是百分比比平均部分高10%以上;因此,我们首先确定单个租金是否高于联合平均* 1.1(或平均租金的110%),如果返回1,否则返回0-即{{1} }语句。我们将每个街区(CASE)的总和除以该街区的游乐设施总数(SUM(CASE ... END)),然后得出百分比。

此查询可以使用窗口函数进行一些重写:

COUNT(*)

在这里,SELECT subq.NAME , SUM(subq.isHigherThan110avg) / COUNT(*) AS percAbove110 FROM (SELECT n.NAME , CASE WHEN r.fare_dollars > 1.1 * AVG(r.fare_dollars) OVER (PARTITION BY n.id) THEN 1.0 ELSE 0 END AS isHigherThan110avg FROM neighborhood n JOIN rentals r ON r.origin_id = n.id ) subq GROUP BY subq.name 子查询使用subq窗口函数与平均内联进行比较,而外部查询只是聚合结果。

Working example on dbfiddle

您当然需要应用自己的过滤器,例如已完成并持续30天,但我希望您能掌握要点。