如何在三个表上使用MAX功能?

时间:2013-06-26 22:36:18

标签: sql postgresql

所以,我的SQL查询有问题。

这是关于获取德国城市的天气数据。我有4个表:staedte(主键loc_id的城市),gehoert_zu(包含城市钥匙和最靠近这个城市的气象站的钥匙(stations_id)),wettermessung(包含所有天气信息和车站的键值)和wetterstation(包含站点键和位置)。我正在使用PostgreSQL

以下是表格的样子:

wetterstation
s_id[PK]   standort    lon    lat    hoehe 
----------------------------------------
10224      Bremen      53.05  8.8    4


wettermessung
stations_id[PK]    datum[PK]     max_temp_2m   ......
----------------------------------------------------
10224              2013-3-24     -0.4


staedte
loc_id[PK]    name    lat    lon
-------------------------------
15            Asch    48.4   9.8


gehoert_zu
loc_id[PK]    stations_id[PK]
-----------------------------
15            10224

我要做的是获取具有(例如)指定日期最高温度(可能是整月或一天)的城市名称。由于天气数据被绑定到一个站点,我实际上需要获取该站点的ID,然后只选择该站点城市对应的一个。一个可能的问题是:“六月哪个城市最热?”而且,最高的测量温度是在10224号站点。因此我想得到Asch这个城市。到目前为止我得到的是这个

SELECT name, MAX (max_temp_2m)
FROM wettermessung, staedte, gehoert_zu 
WHERE wettermessung.stations_id = gehoert_zu.stations_id
    AND gehoert_zu.loc_id = staedte.loc_id 
    AND wettermessung.datum BETWEEN '2012-8-1' AND '2012-12-1' 
GROUP BY name
ORDER BY MAX (max_temp_2m) DESC 
LIMIT 1

结果有两个问题: 1)它花了很长时间。表格不是那么大(城市有大约70,000个条目),但需要1到7分钟才能完成任务(取决于时间跨度) 2)它总是生产同一个城市,我很确定它也不是正确的。

我希望我能够清楚地解释我的问题,我会很高兴能得到任何帮助。提前致谢 ! :d

3 个答案:

答案 0 :(得分:1)

如果您想获得每个城市的最高温度,请使用以下声明:

SELECT * FROM (
   SELECT gz.loc_id, MAX(max_temp_2m) as temperature
      FROM wettermessung as wm
      INNER JOIN gehoert_zu as gz
         ON wm.stations_id = gz.stations_id
      WHERE wm.datum BETWEEN '2012-8-1' AND '2012-12-1' 
      GROUP BY gz.loc_id) as subselect
   INNER JOIN staedte as std
      ON std.loc_id = subselect.loc_id
      ORDER BY subselect.temperature DESC

使用此声明获取温度最高的城市(仅1个城市):

SELECT * FROM(
   SELECT name, MAX(max_temp_2m) as temp
   FROM wettermessung as wm
   INNER JOIN gehoert_zu as gz
      ON wm.stations_id = gz.stations_id
   INNER JOIN staedte as std
      ON gz.loc_id = std.loc_id
   WHERE wm.datum BETWEEN '2012-8-1' AND '2012-12-1' 
   GROUP BY name
   ORDER BY MAX(max_temp_2m) DESC 
   LIMIT 1) as subselect
ORDER BY temp desc
LIMIT 1

出于性能原因,总是使用显式连接作为LEFT,RIGHT,INNER JOIN并避免使用带有分隔表名的连接,所以你的sql serevr不要猜​​测你的表引用。

答案 1 :(得分:0)

这是如何获得具有最高,最低,最大,最小,无论价值的项目的一般示例。您可以根据自己的具体情况进行调整。

select fred, barney, wilma
from bedrock join
(select fred, max(dino) maxdino
from bedrock
where whatever
group by fred ) flinstone on bedrock.fred = flinstone.fred
where dino = maxdino
and other conditions

答案 2 :(得分:0)

我建议你使用一致的命名约定。每行持有单个项目的表的奇异术语是一个很好的约定。你只有表格这是staedte。应该是stadt

我建议始终使用station_id而不是s_idstations_id

在这些前提下,针对您的问题:

  

...获取具有指定日期最高温度的城市名称

SELECT s.name, w.max_temp_2m
FROM  (
   SELECT station_id, max_temp_2m
   FROM   wettermessung
   WHERE  datum >= '2012-8-1'::date
   AND    datum <  '2012-12-1'::date       -- exclude upper border
   ORDER  BY max_temp_2m DESC, station_id  -- id as tie breaker
   LIMIT  1
   ) w
JOIN    gehoert_zu g USING (station_id) -- assuming normalized names
JOIN    stadt      s USING (loc_id)
  • 使用明确的JOIN条件以获得更好的可读性和维护。

  • 使用表别名来简化查询。

  • 使用x >= a AND x < b包含下边框并排除上边框,这是常见用例。

  • 首先聚合并选择具有最高温度的电台,然后再加入其他表格以检索城市名称。更简单,更快捷。

  • 在给定时间范围内多个“wettermessungen”绑定max_temp_2m时,您没有指定要执行的操作。我添加了station_id作为决胜局,这意味着如果有多个符合条件的电台,将会一致地选择ID最低的电台。