SQL / Postgresql如何对列进行分组,但根据某些条件找到另一列的平均值

时间:2018-12-05 16:46:50

标签: sql postgresql postgresql-9.5

我有一个名为 sites 的现有表,该表具有一个或多个具有相同site_id的条目。 我需要使用以下条件创建一个新表:

1)如果有多个具有相同site_id的条目,我必须检查具有相同site_id的两个条目的方位角值,并且如果差值小于10,则求出方位角值的平均值,并且在新表中为它们创建一个条目。 (请参阅现有表中的site_id 5,在新表中获取id 6)

2)如果同一site_id的2个条目大于10度,则每个条目在新表中将获得不同的id。 (请参阅现有表中的site_id 4,在新表中获得2个id的4和5)

3)所有其他具有不同site_id的条目都可以照原样复制,并且每个条目都会在新表中获得一个新ID。 (现有表中除了4和5以外的所有site_id)

现有表站点

            site_id azimuth longitude latitude  
            ------- ------- --------- --------- 
            1       10     -10.93    10.22  
            2       20      5.937    60.43  
            3       30     -7.942    53.47 
            4       70      57.94    13.14  ---> A) Difference of more than 10 degrees with entry below
            4       10      57.94    13.14  ---> A) Difference of more than 10 degrees with entry above

            5       45     -7.92     56.88 --> B) Diff of less than 10 deg with below entry
            5       55     -7.92     56.88 --> B) Diff of less than 10 deg with above entry

带有附加ID列的期望表:

            id      site_id azimuth longitude latitude  
            ------- ------- ------- --------- --------- 
             1         1       10     -10.93    10.22  
             2         2       20      5.937    60.43  
             3         3       30     -7.942    53.47 

             4         4       70      57.94    13.14  // A) Since the difference in azimuth between the 2 entries in above table is more than 10 degrees, each entry goes as separate entries in the new table 

             5         4       10      57.94    13.14   // A) Since the difference in azimuth between the 2 entries in above table is more than 10 degrees, each entry goes as separate entries in the new table

             6         5       50     -7.92     56.88   // B) The azimuth was within 10 degrees with the other entry, so the average of 45+55/2=50 is taken as azimuth for site_id 5 

由于我必须根据10度差异标准找到方位角的平均值,因此我的汇总GROUP BY不适用于所有条目。 我是SQL的新手,希望能对此提供任何帮助。

2 个答案:

答案 0 :(得分:1)

这是一个复杂的问题。一种方法是使用窗口函数将所有可用信息收集到潜在的列中。然后,使用简单过滤来确定要采用的列:

select site_id,
       (case when max_azimuth - min_azimuth < 10 then avg_azimuth
             else azimuth
        end) as azimuth, longitude, latitude
from (select site_id, azimuth, longitude, latitude,
             row_number() over (partition by site_id) as seqnum,
             count(*) over (partition by site_id) as cnt,
             avg(azimuth) over (partition by site_id) as avg_azimuth,
             min(azimuth) over (partition by site_id) as min_azimuth,
             max(azimuth) over (partition by site_id) as max_azimuth
      from sites site_id
     ) t
where cnt = 1 or
      (seqnum = 1 and (max_azimuth - min_azimuth) < 10) or
      (max_azimuth - min_azimuth) >= 10;

答案 1 :(得分:0)

我们可以分两步进行:

  • 步骤1:创建一个按site_id分组的表,该表确定是否应合并具有该site_id的站点

  • 第2步:将其与原始表连接以在必要时提取非组合数据

结果如下:

select row_number() over () AS id
 , s2.site_id
 , case when t.close_azimuths then avg_azimuth else s2.azimuth end as azimuth
 , s2.longitude
 , s2.latitude
from 
  (select site_id
   , max(azimuth) - min(azimuth) <= 10 as close_azimuths
   , avg(azimuth) as avg_azimuth
  from sites
  group by site_id ) t
join sites s2 on s2.site_id = t.site_id

group by s2.site_id
 , case when t.close_azimuths then avg_azimuth else s2.azimuth end
 , s2.longitude
 , s2.latitude

请注意,新的方位角列不是整数,因为它是整数行的平均值。如果方位角读数应为整数,则可以使用:: integer舍入并强制返回整数