Search code examples
postgresqlpostgresql-8.3

aggregate function to keep specific value, depending of other columns


I have data of the following format

 id_A       id_B        val
--------------------------------
 1           1           1
 1           2           2  
 2           1           3
 2           3           4  

Is there a nice way to group by id_A while keeping the value of the line where id_A = Id_B ?

The reason I need to aggregate is that if there is no such line, I want the average.

The result should look like this:

 id_A       val
-----------------
 1           1
 2           3.5

I've come up with the following, but that case looks ugly and hacky to me.

Select id_A,
    Coalesce(
        avg(case when id_A = id_B then val else null end),
        avg(val)
    ) as value
From myTable
Group by id_A; 

Solution

  • With postgres 9.4+ you can use FILTER clause for aggregates and window functions:

    functions. Something like this:
    Select id_A,
        Coalesce(
            avg(val) filter(where id_A = id_B),
            avg(val)
        ) as value
    From myTable
    Group by id_A; 
    

    Details here:http://www.postgresql.org/docs/current/static/sql-expressions.html