SQL, чтобы получить общий непогашенный остаток, отвечающий критериям снятия - PullRequest
2 голосов
/ 18 мая 2011

У меня есть таблица платежей, в которой есть user_id и сумма. Минимальный вывод для пользователей составляет 5 долларов США, и они могут получать любое количество платежей. Их общий баланс нигде не хранится (для простоты и избежания проблем с синхронизацией), вместо этого его можно найти, выполнив запрос:

SELECT SUM(amount) 
  FROM payment 
 WHERE user_id = 5;

Я хочу узнать общую сумму всех остатков, которые отвечают требованию на снятие средств. То, что я хотел бы сделать, это что-то вроде:

  SELECT SUM(SUM(amount)) 
    FROM payment 
   WHERE sum(amount) >= 5.00
GROUP BY user_id;

К сожалению, я получаю ошибку

ОШИБКА: агрегаты не разрешены в предложении WHERE

Как мне написать этот запрос? Я использую postgres 8.4.

Часть 2:

Я не уверен, что это вообще возможно, но эта таблица платежей также включает платежи, сделанные пользователем : таблица платежей включает в себя сумму, from_user_id и to_user_id. Это однократная учетная система. Было бы здорово, если бы я мог также вычесть платежи, сделанные пользователем. Псевдо-sql это:

SELECT (sum of all amounts) 
 WHERE (sum(amount where to_user_id = 5) - sum(amount where from_user_id = 5)) > 5.00

Ответы [ 3 ]

2 голосов
/ 18 мая 2011

Вам необходимо использовать предложение HAVING

Никогда не слышал, чтобы кто-то пытался сделать вложенную агрегацию. Я предлагаю вам делать внутренний бит отдельно, либо с with комментарием, либо используя что-то вроде

select sum(foo) from (select sum(amount) as foo ...having ...)

Я полагаю, что вы хотите что-то подобное для своей второй части, хотя, возможно, я догадываюсь.

with a as(
  select sum(amount) as credit, from_user from payment group by from_user
), b as (
  select sum(amount) as debit, to_user from payment group by to_user
)
-- glossing over any null values with coalesce:
select to_user, coalesce(credit,0) - coalesce(debit,0) -- coalesce users perhaps?
from a outer join b on from_user = to_user
where coalesce(credit,0) - coalesce(debit,0) > limit -- or vice-versa
1 голос
/ 18 мая 2011

Часть 1. Агрегаты и предложение HAVING

В SQL предложение WHERE не поддерживает использование агрегата (IE: MIN, MAX, SUM, COUNT и т. Д.), Который не являетсявнутри подзапроса или производной таблицы / встроенного представления.Такие случаи могут быть обработаны только в предложении HAVING:

  SELECT SUM(p.amount) 
    FROM PAYMENT p
GROUP BY p.to_user_id
  HAVING SUM(p.amount) >= 5.00

Часть 2:

Поскольку пользователь может получать только платежи на свой счет, или наоборот - вам нужно получитьсписок пользователей для внешнего присоединения к:

   SELECT COALESCE(x.debit, 0) - COALESCE(y.credit, 0) AS balance
     FROM (SELECT a.from_user_id AS user
             FROM PAYMENT a
           UNION 
           SELECT b.to_user_id
             FROM PAYMENT b) z
LEFT JOIN (SELECT t.to_user_id,
                  SUM(t.payment) AS debit
             FROM PAYMENT t
         GROUP BY t.to_user_id) x ON x.to_user_id = z.user
LEFT JOIN (SELECT t.from_user_id,
                  SUM(t.payment) AS credit
             FROM PAYMENT t
         GROUP BY t.from_user_id) y ON y.from_user_id = z.user
    WHERE COALESCE(x.debit, 0) - COALESCE(y.credit, 0) >= 5.00
 GROUP BY z.user
1 голос
/ 18 мая 2011

Вы захотите использовать предложение HAVING.

Следующее даст вам всех пользователей, которые имеют баланс больше 5,00. Затем вы можете перейти на свой язык программирования, чтобы получить общий баланс. SELECT sum(amount) FROM payment GROUP BY user_id HAVING sum(amount) >= 5.00 ;

Я не могу придумать, как объединить все это в один эффективный оператор SQL, но я продолжу думать.

Не думаю, что у меня тоже есть ответ на вашу часть 2. Прошу прощения.

...