Запрос агрегации SQL для SUM, но разрешать только положительные суммы (иначе 0)

Я хочу запросить таблицу заказов и показать идентификатор клиента и общую сумму всех его заказов, однако заказы могут иметь положительные или отрицательные итоги.

select customer_id, SUM(order_total) from orders group by customer_id;

Теперь мой вопрос - как я могу добиться следующего в одном запросе sql:

Если общая сумма положительная, я хочу отобразить ее как есть; если общая сумма отрицательна, я просто хочу отобразить 0 вместо фактической суммы.

Я ищу функцию, которая может справиться с этим, похожую на функцию IFNULL (IFNULL(SUM(order_total),0)), но вместо проверки нулевого значения она должна проверять отрицательный результат.

Псевдокод:

IFNEGATIVE(SUM(order_total),0)

Есть ли простой способ в стандартном sql (или, в частности, в Mysql 5.5, тоже будет нормально).


person Mathias Conradt    schedule 05.07.2011    source источник


Ответы (7)


SELECT customer_id,
  CASE 
    WHEN SUM(order_total) < 0 THEN 0
    ELSE SUM(order_total)
  END
  FROM orders 
  GROUP BY customer_id;

Проверьте свой план выполнения, но 2 SUM, вероятно, будут оптимизированы для одного SUM под капотом.

person dee-see    schedule 05.07.2011
comment
Большое спасибо, я не часто использовал случаи в sql, полезно знать :) Я думаю, что некоторые из других предоставленных ответов (т.е. IF также работают), однако позвольте мне принять это голосование здесь, я также поддерживаю другие . - person Mathias Conradt; 05.07.2011

Попробуйте с:

select customer_id, GREATEST( SUM(order_total),0) from orders group by customer_id;
person Tudor Constantin    schedule 05.07.2011
comment
Мне это также больше нравится из-за удобочитаемости/ремонтопригодности, но быстрая проверка с моей стороны для аналогичного сценария показывает тот же план выполнения в SQL 2012 - SQL-сервер может понять, что вам это действительно нужно только один раз. - person Dan Field; 07.01.2016
comment
И я понимаю, что это старый вопрос, и только что увидел, что он на самом деле для MySQL, но это похоже на довольно простую оптимизацию - держу пари, что MySQL тоже может это сделать. - person Dan Field; 07.01.2016

Не проверено, но что-то вроде этого должно сделать это:

SELECT customer_id , IF( SUM(order_total) > 0, SUM(order_total), 0) AS sum FROM orders GROUP BY customer_id
person Thorsten    schedule 05.07.2011

Не могли бы вы использовать оператор CASE?

Что-то типа:

CASE WHEN [Field] < 0 THEN 0

Или я что-то пропустил?

person CatchingMonkey    schedule 05.07.2011
comment
ты что-то пропустил. это сумма, которая не должна быть отрицательной — отдельные строки можно смешивать +ve и -ve, если сумма не является отрицательной - person Bohemian♦; 05.07.2011
comment
это казалось слишком простым! Спасибо. - person CatchingMonkey; 05.07.2011

если я понимаю, что это только оберните его GREATEST

SELECT customer_id, GREATEST(0,SUM(order_total)) 
FROM orders GROUP BY customer_id;

просмотрите ссылку

person Haim Evgi    schedule 05.07.2011
comment
Это суммирует только положительные ордера. ОП запрашивает сумму всех заказов. - person ypercubeᵀᴹ; 05.07.2011

Вы также можете попробовать;

select 
  (sum(fld) + abs(sum(fld))) / 2
from tbl
person Alex K.    schedule 05.07.2011
comment
не должно ли быть (сумма(флд) + сумма(абс((флд))) / 2 - person Sano J; 30.12.2014

Чтобы отображать только положительные значения, используйте HAVING таким образом:

select customer_id, SUM(order_total) from orders group by customer_id HAVING SUM(order_total) > 0;

В противном случае используйте случай, как указано в другом месте здесь

person Justin Wignall    schedule 05.07.2011
comment
Это ограничит его поиск, но не будет отображать 0, когда сумма будет отрицательной. - person dee-see; 05.07.2011
comment
Понял, что неправильно понял «нулевой дисплей», но оставил ответ здесь для других случаев... - person Justin Wignall; 05.07.2011