SQL/ Postgresql如何对列进行分组,但根据特定条件求另一列的平均值
SQL/ Postgresql How to group on column but find the average of another column based on certain conditions
我有一个名为 sites 的现有 table,其中有一个或多个具有相同 site_id 的条目。
我需要根据以下条件创建一个新的 table:
1) 如果有多个条目具有相同的 site_id,我必须检查具有相同 site_id 的两个条目的方位角值,如果差异小于 10 ,然后获取方位角值的平均值,并在新的 table 中为它们创建一个条目。 (请参阅现有 table 中的 site_id 5,它在新的 table 中获得 id 6)
2) 如果相同 site_id 的 2 个条目超过 10 度,则每个条目在新的 table 中获得不同的 ID。 (请参阅现有 table 中的 site_id 4,在新 table 中获得 2 id 的 4 和 5)
3) 所有其他具有不同 site_id 的条目都可以按原样复制,每个条目都会在新的 table 中获得一个新的 ID。 (现有 table 中除 4 和 5 外的所有 site_id)
现有 TABLE 站点:
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
EXPECTED TABLE 带有额外的 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 的新手,如果能得到任何帮助,我将不胜感激。
这是一个复杂的问题。一种方法是使用 window 函数将所有可用信息收集到潜在列中。然后,使用简单的过滤来确定要取哪些列:
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 步:根据 site_id 创建一个 table 分组,确定是否应合并具有 site_id 的站点
第 2 步:将其与原始 table 合并以在必要时引入未合并的数据
结果如下:
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
舍入并强制返回整数
我有一个名为 sites 的现有 table,其中有一个或多个具有相同 site_id 的条目。 我需要根据以下条件创建一个新的 table:
1) 如果有多个条目具有相同的 site_id,我必须检查具有相同 site_id 的两个条目的方位角值,如果差异小于 10 ,然后获取方位角值的平均值,并在新的 table 中为它们创建一个条目。 (请参阅现有 table 中的 site_id 5,它在新的 table 中获得 id 6)
2) 如果相同 site_id 的 2 个条目超过 10 度,则每个条目在新的 table 中获得不同的 ID。 (请参阅现有 table 中的 site_id 4,在新 table 中获得 2 id 的 4 和 5)
3) 所有其他具有不同 site_id 的条目都可以按原样复制,每个条目都会在新的 table 中获得一个新的 ID。 (现有 table 中除 4 和 5 外的所有 site_id)
现有 TABLE 站点:
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
EXPECTED TABLE 带有额外的 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 的新手,如果能得到任何帮助,我将不胜感激。
这是一个复杂的问题。一种方法是使用 window 函数将所有可用信息收集到潜在列中。然后,使用简单的过滤来确定要取哪些列:
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 步:根据 site_id 创建一个 table 分组,确定是否应合并具有 site_id 的站点
第 2 步:将其与原始 table 合并以在必要时引入未合并的数据
结果如下:
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
舍入并强制返回整数