2013-06-20 3 views
3

У меня есть эта таблицаPostgreSQL - Условный агрегация - Avg() в заявлении Выберите

| user   | Mark  | Points | 
|--------------|------------|----------| 
| John   | 0  | 2  | 
| Paul   | 5  | 3  | 
| John   | 4  | 4  | 
| Paul   | 7  | 5  | 

Я хотел бы построить запрос с одним оператором выбора, который возвращает строки, показанные ниже. Среднее (Mark) - должно быть средним, только если Mark> 0 Сумма (баллы) - должна быть суммой всех записей.

| user   | Avg(Mark) | Sum(Points) | 
|--------------|------------|-------------| 
| John   | 4  | 6  | 
| Paul   | 6  | 8  | 

Может ли кто-нибудь указать на правильный синтаксис?

Я считаю, что это должно понравиться:

select user, avg(Mark>0), sum(Points) from Table group by user; 

ответ

7

Как насчет:

select user, 
     avg(case when mark > 0 then mark end), 
     sum(mark) 
from ... 
1
select 
    user, -- very bad choice for column name, but i assume it's just SO example, not real column 
    sum(mark)/count (nullif(mark, 0)) 
from 
    table 
group by 
    user 

должен так трюк.

+0

есть также возможность, как избежать деления на ноль в случае «John» имеет нулевые значения всех «Marks»? – Fridolin

+1

Я думаю, что я отработал его (знак)/nullif (count (nullif (mark, 0)), 0) Еще раз спасибо за вашу помощь. – Fridolin

0

Начиная с версии 9.4, PostgreSQL непосредственно поддерживает агрегаты фильтрации.

https://www.postgresql.org/docs/9.4/static/sql-expressions.html

Если указан ФИЛЬТР, то только входные строки, для которых filter_clause вычисляется как истина подаются в агрегатной функции; другие строки отбрасываются.

С его помощью, ваш пример можно переписать следующим образом:

SELECT 
    "user", 
    AVG(mark) FILTER (WHERE mark > 0), 
    SUM(points) 
FROM 
    "table" 
GROUP BY 
    "user" 
Смежные вопросы