所以,我的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
答案 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_id
和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
包含下边框并排除上边框,这是常见用例。
首先聚合并选择具有最高温度的电台,然后再加入其他表格以检索城市名称。更简单,更快捷。
在给定时间范围内多个“wettermessungen”绑定max_temp_2m
时,您没有指定要执行的操作。我添加了station_id
作为决胜局,这意味着如果有多个符合条件的电台,将会一致地选择ID最低的电台。