在 SQL 中编写多个子查询是否有更好的替代方法?

Is there a better alternative to writing multiple subqueries in SQL?

我在 Redash 上查询以提取带有定价网格的停车位汇总列表。清单 table 包含停车详细信息(姓名、地址 link)和多个价格栏,具体取决于停留时间。

我正在使用两个 table(停车和优惠)。优惠 table 具有三个字段,park_id、价格和持续时间。每个 park_id 的价格可能与特定的停留时间相对应。例如,公园 #1 将收取 3600 秒 2 美元,86400 秒 30 美元等。

我已经编写了单独的子查询来获取每个持续时间的这些价格,从 1 小时到 24 小时(1 天),然后持续到 31 天,然后持续 93 天、186 天和 372 天。总共有57个子查询。

结果table有57列价格(price1h,price2h….price1d,price 2d…..price31d,price93d,price186d,price372d)。

条件: 我必须使用两个重要条件才能获得价格。一个是 offers.duration = 3600/7200 等,然后我筛选出套餐类型而非订阅类型的报价。最后,AND offers.park_id = parks.id links 来自 tables park 和 offers 的两个关键字段。

问题是我在不同的持续时间内多次重复这个子查询,执行速度非常慢并且超过了“Redash 查询执行时间限制”

查询片段如下:

SELECT DISTINCT parkid AS ID,
park_name AS Name,
park_address AS full_address,
park_url_description AS park_url,

      (SELECT offers.price
          FROM offers
          WHERE offers.type = 'package'
            AND offers.duration = 3600
            AND offers.park_id = park.parkid) AS price1h,
         
           (SELECT offers.price
           FROM offers
           WHERE offers.type = 'package'
           AND offers.duration = 7200
           AND offers.park_id = park.parkid) AS price2h,       

          (SELECT offers.price
          FROM offers
          WHERE offers.type = 'package'
          AND offers.duration = 10800
          AND offers.park_id = park.parkid) AS price3h,       
          …….. /* and so on */
FROM park
LEFT JOIN offers ON park.parkid = offers.park_id
GROUP BY id, Name, full_address, park_url

结果table是这样的: https://i.stack.imgur.com/0opp0.png

谁能推荐一个更好的替代方案来获得这些价格?我尝试使用 CTE 方法,但我没有足够的经验,所以我无法想出解决方案(我是一名实习生,仍在学习中。) 提前谢谢你。

假设每个公园+持续时间有一个报价,您可以通过有条件地使用聚合函数来实现:

SELECT 
  p.parkid AS ID,
  p.park_name AS Name,
  p.park_address AS full_address,
  p.park_url_description AS park_url,
  max(if (o.duration = 3600, o.price, null)) as price1h,
  max(if (o.duration = 7200, o.price, null)) as price2h,
  max(if (o.duration = 10800, o.price, null)) as price3h
FROM park p
  LEFT JOIN offers o ON p.parkid = o.park_id and o.type = 'package'
  AND o.duration in (3600, 7200, 10800)
GROUP BY p.parkid, p.park_name, p.park_address, p.park_url_description

dbfiddle