简体   繁体   English

如何获得 PostgreSQL 中的两个平均值之间的差异,其中平均值在一列上,而最终表格按两列分组?

[英]How to get difference between two average values in PostgreSQL, where the averages are on a column, and the final table grouped by two columns?

I want to know the difference between two averages of value , where each average is filtered by a condition isCool to be either True or False , and the final result grouped by town and season , eg我想知道两个平均值之间的差异value ,其中每个平均值都按条件isCool过滤为TrueFalse ,最终结果按townseason分组,例如

table

| id | value | isCool | town   | season |
|----|-------|--------|--------|--------|
| 0  | 1     | True   | TownA  | spring |
| 1  | 2     | False  | TownA  | winter |
| 2  | 3     | True   | TownB  | spring |
| 3  | 4     | False  | TownA  | winter |
| 4  | 5     | False  | TownB  | spring |
| 5  | 6     | True   | TownB  | winter |

I want to end up with the table:我想以表格结束:

| category | difference_of_is_cool_averages |
|----------|--------------------------------|
| TownA    | 2                              | <-- ABS(1 - (2 + 4)/2)
| TownB    | 0.5                            | <-- ABS(5 - (3 + 6)/2)
| spring   | 3                              | <-- ABS(5 - (3 + 1)/2)
| winter   | 3                              | <-- ABS(6 - (4 + 2)/2)

I have attempted this but my PostgreSQL skills are limited and I did not get far at all, unfortunately.我已经尝试过了,但不幸的是,我的 PostgreSQL 技能有限,我根本没有走多远。 I tried我试过

SELECT
   AVG(value), town
   (SELECT id, value, town, season
   FROM table
   WHERE isCool = 'True') AS TableSummary1
GROUP BY town;

but this is far from what I want.但这远非我想要的。 Is someone able to help please?有人可以帮忙吗? Is this even possible with PostgreSQL? PostgreSQL 甚至可能吗?

You can unpivot, and then compute the difference between the two conditional averages of each group:您可以取消透视,然后计算每组的两个条件平均值之间的差异:

select x.category, 
    abs(avg(t.value) filter(where not t.iscool) - avg(t.value) filter(where t.iscool)) diff
from mytable t
cross join lateral (values (town), (season)) as x(category)
group by x.category

If you want to be able to order the resultset as showed in the desired results, then we need to keep track of the original column:如果您希望能够按照所需结果中所示对结果集进行排序,那么我们需要跟踪原始列:

select x.category, 
    abs(avg(t.value) filter(where not t.iscool) - avg(t.value) filter(where t.iscool)) diff
from mytable t
cross join lateral (values (town, 1), (season, 2)) as x(category, grp)
group by x.category, x.grp
order by x.grp

Demo on DB Fiddle : DB Fiddle 演示

category |                   diff
:------- | ---------------------:
TownB    |     0.5000000000000000
TownA    | 2.00000000000000000000
winter   |     3.0000000000000000
spring   |     3.0000000000000000

Here Union All will help you.在这里, Union All将为您提供帮助。 Simply calculate the difference of average once by grouping town then by grouping season and union them.简单地通过对town进行分组然后通过对season进行分组并合并它们来计算一次平均值的差异。 You can write your query like below:您可以像下面这样编写查询:

select
town "Category",
round(abs(avg(value) filter (where iscool='t') - avg(value) filter (where iscool='f')),2) "difference_of_is_cool_averages"
from town
group by town

union all

select
season,
round(abs(avg(value) filter (where iscool='t') - avg(value) filter (where iscool='f')),2)
from town
group by season

DEMO 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM