3

所以,我对 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,然后选择与该站对应的城市之一。一个可能的问题是:“6 月份哪个城市最热?” 比如说,测得的最高温度是在 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)花费的时间太长了。表格不是那么大(城市有大约 70k 条目),但它需要 1 到 7 分钟才能完成(取决于时间跨度)2)它总是产生同一个城市,我很确定它不是对的一个。

我希望我能够足够清楚地解释我的问题,并且我很乐意提供任何帮助。提前致谢 !:D

4

3 回答 3

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 不必猜测您的表引用。

于 2013-06-26T23:08:09.783 回答
0

我建议您使用一致的命名约定。每行包含一个项目的表的单数术语是一个很好的约定。你唯一的表打破这是staedte。应该是stadt

我建议station_id始终使用而不是s_idand stations_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包含下边框并排除上边框,这是常见的用例。

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

  • max_temp_2m当多个“wettermessungen”在给定的时间范围内捆绑时,您没有指定要做什么。我添加station_id为决胜局,这意味着如果有多个符合条件的电台,将始终选择 ID 最低的电台。

于 2013-06-27T00:26:03.727 回答
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
于 2013-06-26T22:56:19.667 回答