0

我对复杂的 SQL 请求很陌生...

我想要实现的是在传单地图页面上显示活动天气警报的地图。

首先使用来自国家气象机构的 RSS 提要填充 Postgis 表,然后通过选择过期日期晚于实际日期的 ROW 并通过 Geoserver WFS 服务发布此视图来创建视图。

看起来不错,只是每个地理区域都添加了多个事件有效过期功能,从而导致了一种仅显示顶部事件的多层。

我遇到的问题是,对于每个区域/多边形,我都有多条线用于我必须整理的杂项事件/日期。

初始表的结构如下:

     areadesc(county)|event(type of alert)|effective(date)|expires(date)|severity(low,medium,severe)

我试图解决这个烂摊子的方法是:首先为每个事件创建一个视图,以便每个位置只有“此类事件”的最新过期警报:

SELECT DISTINCT ON (country.areadesc) 
    country.areadesc,
    country.event,
    country.effective,
    country.expires,
    country.severity
FROM 
    country
WHERE 
    country.expires >= now() AND now() >= country.effective 
    AND country.event::text = 'Thunderstorms'::text
ORDER BY 
    country.areadesc, country.expires;

我对每个我感兴趣的事件都这样做了。

其次,我为每个区域创建了一个聚合视图,其中包含相关事件类型的内容:

SELECT DISTINCT 
    country.areadesc,
    country_thunderstorms.severity AS thunderstorms_severity,
    country_thunderstorms.effective AS thunderstorms_effective,
    country_rain.effective AS rain_effective,
    country_rain.expires AS rain_expires,
    country_districts.geom
FROM 
    country_alerts
LEFT JOIN 
    country_thunderstorms ON country.areadesc::text = country_thunderstorms.areadesc::text
LEFT JOIN 
    country_wind ON country.areadesc::text = country_wind.areadesc::text
LEFT JOIN 
    country_rain ON country.areadesc::text = country_rain.areadesc::text
LEFT JOIN 
    country_districts ON country.areadesc::text = country_districts.name_en::text
WHERE 
    country.expires >= now() AND now() >= country.effective 
    AND (country.title::text = ANY (ARRAY['Thunderstorms'::character varying, 'Wind'::character varying, 'Rain'::character varying]::text[]))
ORDER BY 
    country.areadesc;

所有这些东西都可以完成这项工作,但看起来更像是一把锤子来杀死一只苍蝇。

我确信有一种方法可以通过嵌套 SELECT 在一次运行中实现这一点,但绝对无法弄清楚如何:-(

欢迎任何建议,感谢您的帮助。

4

1 回答 1

0

我不确定我是否回答了您的问题,但您可以尝试窗口函数,例如 dense_rank() 来对您的行进行排名。

SELECT 
country,
event_type,
effective_date,
expires,
severity,
dense_rank() 
OVER(PARTITION BY country,event_type 
     ORDER BY effective_date desc, expires desc) as rnk
FROM weather

然后在其上编写一个外部查询以仅获得第一名。

SELECT * FROM (
SELECT 
country,
event_type,
effective_date,
expires,
severity,
dense_rank() 
OVER(PARTITION BY country,event_type 
     ORDER BY effective_date desc, expires desc) as rnk
FROM weather) X WHERE rnk=1
国家 事件类型 生效日期 过期 严重性 rnk
印度 2021-08-01T00:30:01Z 2021-08-01T00:36:34Z 中等的 1
印度 2021-08-01T00:22:01Z 2021-08-01T02:03:34Z 中等的 2
印度 2021-08-01T00:00:01Z 2021-08-01T00:24:34Z 中等的 3
印度 雷雨 2021-08-01T00:32:01Z 2021-08-01T00:32:34Z 低的 1
印度 雷雨 2021-08-01T00:30:01Z 2021-08-01T00:23:34Z 中等的 2
印度 雷雨 2021-08-01T00:11:01Z 2021-08-01T00:10:34Z 高的 3
印度 2021-08-01T00:10:01Z 2021-08-01T01:05:34Z 低的 1
印度 2021-08-01T00:00:01Z 2021-08-01T04:01:34Z 低的 2
印度 2021-08-01T00:00:01Z 2021-08-01T00:25:34Z 低的 3

编辑

根据您的回答,我了解到您正在寻找如下所示的数据透视结果。

select * from weather where rnk=1;
国家 事件类型 生效日期 过期 严重性 rnk
印度 2021-08-01T00:30:01Z 2021-08-01T00:36:34Z 中等的 1
印度 雷雨 2021-08-01T00:32:01Z 2021-08-01T00:32:34Z 低的 1
印度 2021-08-01T00:10:01Z 2021-08-01T01:05:34Z 低的 1
select 
country, 
max(case when (event_type='Rain') then severity else NULL end) as         
Rain_Severity,
max(case when (event_type='Rain') then effective_date else NULL end) as 
Rain_Effective_date,
max(case when (event_type='Rain') then expires else NULL end) as 
Rain_expires,
max(case when (event_type='thunderstorm') then severity else NULL end) 
as Thunderstorm_Severity,
max(case when (event_type='thunderstorm') then effective_date else NULL 
end) as Thunderstorm_Effective_date,
max(case when (event_type='thunderstorm') then expires else NULL end) as 
Thunderstorm_expires,
max(case when (event_type='Wind') then severity else NULL end) as 
Wind_Severity,
max(case when (event_type='Wind') then effective_date else NULL end) as 
Wind_Effective_date,
max(case when (event_type='Wind') then expires else NULL end) as 
Wind_expires
from weather 
where rnk=1
group by country;
国家 rain_severity 雨有效日期 rain_expires 雷暴_严重性 雷暴生效日期 雷暴_过期 wind_severity wind_effective_date wind_expires
印度 中等的 2021-08-01T00:30:01Z 2021-08-01T00:36:34Z 低的 2021-08-01T00:32:01Z 2021-08-01T00:32:34Z 低的 2021-08-01T00:10:01Z 2021-08-01T01:05:34Z
于 2021-08-01T13:10:41.557 回答