构建 SQL 查询,汇总不同类别和不同条件的总值

Build SQL query that summarizes total values for different categories and varying criteria

我正在使用 PostgreSQL 9.6,我正在尝试在一个 table 上创建一个查询,该查询可以汇总不同站点中一个类别的总面积。 下面是我的 table 的简化版本。

Id  |  category (text)  |  area (real)  |  site (text)
 1  |   short grass 1   |      10       |     park 1
 2  |   short grass 2   |      15       |     park 2
 3  |   long grass 1    |      25       |     park 1
 4  |   long grass 2    |      18       |     park 3
 5  |   short grass 1   |      7        |     roadside 1
 6  |   short grass 2   |      4        |     roadside 2
 7  |   long grass 1    |      14       |     roadside 1
 8  |   long grass 2    |      7        |     roadside 3

我的目标 table 是按草类(第 2 列)和场地(第 4 列)分类的总面积:

    site (text)        |  short grass   |  long grass
                          total area       total area
  park (grouped)       |      25        |      43
 roadside (grouped)    |      11        |      21

我认为我在 SUM 函数中使用 CASE WHEN 语句取得了一些成功,但它没有根据不同的标准创建具有面积总计的多行,而是将它们添加到单个 SUM 中,事后我意识到这就是我要求它做的。 (下面是我的代码的一个简短示例):

SELECT SUM(CASE WHEN category LIKE 'short grass%' AND site LIKE 'park%' THEN area
    WHEN category LIKE 'long grass%' AND site LIKE 'park%' THEN area END) 
from my_table;

我期待的是两行不同的面积总数。这就是我的代码,我认为我什至没有朝着正确的方向前进。

我考虑过嵌套 SELECT 查询和连接,但我的 SQL 知识不是很好,所以我不知道从哪里开始写。

我想这就是你想要做的。

SELECT case when site like 'park%' then 'park' 
            when site like 'roadside%' then 'roadside' 
       --add else if required
       end as site,
SUM(CASE WHEN category LIKE 'short grass%' THEN area ELSE 0 END) as short_grass
SUM(CASE WHEN category LIKE 'long grass%' THEN area ELSE 0 END) as long_grass
from my_table
group by case when site like 'park%' then 'park' 
              when site like 'roadside%' then 'roadside' 
         --add else if required
         end

你是如何定义群体的?如果您只想要 site 中的第一个单词,那么:

select substring(site from '#"%#" %' for '#') as sitetype,
       sum(case when category like 'short grass%' then area else 0 end) as shortgrass,
       sum(case when category like 'long grass%' then area else 0 end) as longgrass
from my_table
group by sitetype;