SQL / Postgresql Как группировать по столбцу, но найти среднее значение для другого столбца на основе определенных условий - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть таблица с именем sites , в которой есть одна или несколько записей с одинаковым идентификатором site_id.Мне нужно создать новую таблицу по следующим критериям:

1) Если существует более одной записи с одинаковым site_id, я должен проверить значения азимута обеих записей с одинаковым site_id, и еслиРазница меньше 10, тогда получите среднее значение азимута, и для них будет создана отдельная запись в новой таблице.(см. site_id 5 в существующей таблице, которая получает идентификатор 6 в новой таблице)

2) если 2 записи для одного и того же site_id превышают 10 градусов, то каждая получает новый идентификатор в новой таблице.(См. Site_id 4 в существующей таблице, который получает 2 идентификатора 4 и 5 в новой таблице)

3) Все остальные записи, которые имеют отличный site_id, могут быть скопированы как есть, и каждая получает новый идентификатор вновый стол(Все site_ids, кроме 4 и 5 в существующей таблице)

СУЩЕСТВУЮЩАЯ ТАБЛИЦА САЙТЫ :

            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      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 голосов
/ 06 декабря 2018

Мы можем сделать это в два этапа:

  • Шаг 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

0 голосов
/ 05 декабря 2018

Это сложный вопрос.Один из подходов заключается в использовании оконных функций для сбора всей доступной информации в потенциальные столбцы.Затем используйте простую фильтрацию, чтобы определить, какие столбцы взять:

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;
...