如何在嵌套 SELECT 查询 Postgresql 中聚合多行

How to aggregate multiple rows in nested SELECT query Postgresql

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

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

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

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

我遇到的问题是,对于每个 area/polygon,我都有多行杂项 events/dates 需要整理。

最初的table结构像:

     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 来实现这一点,但绝对不知道如何:-(

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

我不确定我是否回答了您的问题,但您可以尝试 window 函数,例如 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
country event_type effective_date expires severity rnk
India Rain 2021-08-01T00:30:01Z 2021-08-01T00:36:34Z Medium 1
India Rain 2021-08-01T00:22:01Z 2021-08-01T02:03:34Z Medium 2
India Rain 2021-08-01T00:00:01Z 2021-08-01T00:24:34Z Medium 3
India thunderstorm 2021-08-01T00:32:01Z 2021-08-01T00:32:34Z Low 1
India thunderstorm 2021-08-01T00:30:01Z 2021-08-01T00:23:34Z Medium 2
India thunderstorm 2021-08-01T00:11:01Z 2021-08-01T00:10:34Z High 3
India Wind 2021-08-01T00:10:01Z 2021-08-01T01:05:34Z Low 1
India Wind 2021-08-01T00:00:01Z 2021-08-01T04:01:34Z Low 2
India Wind 2021-08-01T00:00:01Z 2021-08-01T00:25:34Z Low 3

编辑

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

select * from weather where rnk=1;
country event_type effective_date expires severity rnk
India Rain 2021-08-01T00:30:01Z 2021-08-01T00:36:34Z Medium 1
India thunderstorm 2021-08-01T00:32:01Z 2021-08-01T00:32:34Z Low 1
India Wind 2021-08-01T00:10:01Z 2021-08-01T01:05:34Z Low 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;
country rain_severity rain_effective_date rain_expires thunderstorm_severity thunderstorm_effective_date thunderstorm_expires wind_severity wind_effective_date wind_expires
India Medium 2021-08-01T00:30:01Z 2021-08-01T00:36:34Z Low 2021-08-01T00:32:01Z 2021-08-01T00:32:34Z Low 2021-08-01T00:10:01Z 2021-08-01T01:05:34Z