Синтаксическая ошибка SQL внутри ПРИВЕДЕНИЯ с помощью оператора case

#sql #postgresql #casting #case #aggregate-functions

#sql #postgresql #Кастинг #случай #агрегатные функции

Вопрос:

Я хочу перечислить положительные и отрицательные bank_transfers значения из моей базы данных. Для этого я использую запрос ниже:

 SELECT
  bank_transfers.date AS day,
  CAST(SUM(CASE WHEN bank_transfers.amount_cents < 0 THEN bank_transfers.amount_cents END)) AS sum_expenses,
  CAST(SUM(CASE WHEN bank_transfers.amount_cents > 0 THEN bank_transfers.amount_cents END)) AS sum_revenue
FROM bank_transfers
JOIN customers ON customers.id = bank_transfers.customer_id
WHERE customers.id = 1
AND bank_transfers.date < '2020-11-26'
AND bank_transfers.date >= '2020-08-26'
GROUP BY DAY
 

Но это выдает ошибку syntax error at or near ")" . Я предполагаю, что это происходит из CAST so, где я должен закрыть круглые скобки?

Ответ №1:

Вам даже не нужны эти приведения. Вы не выполняете приведение ни к какому типу (если sum_expenses только и sum_revenue не являются вашими пользовательскими типами).

Редактировать: если вы хотите привести к целому числу:

 SELECT
  bank_transfers.date AS day,
  SUM(CASE WHEN bank_transfers.amount_cents < 0 THEN bank_transfers.amount_cents END)::integer AS sum_expenses,
  SUM(CASE WHEN bank_transfers.amount_cents > 0 THEN bank_transfers.amount_cents END)::integer AS sum_revenue
FROM bank_transfers
JOIN customers ON customers.id = bank_transfers.customer_id
WHERE customers.id = 1
AND bank_transfers.date < '2020-11-26'
AND bank_transfers.date >= '2020-08-26'
GROUP BY DAY
 

Или использовать cast(... as integer) .

Комментарии:

1. Без CAST этого я получу число с плавающей запятой, например -4441.0 , вместо -4441

2. @mr_muscle добавьте ::integer или cast(... as integer) . Я обновил свой ответ

3. @mr_muscle нет, CAST(SUM(CASE WHEN bank_transfers.amount_cents < 0 THEN bank_transfers.amount_cents END) as integer) AS sum_expenses

Ответ №2:

Вам даже не нужно a JOIN для этого запроса, потому что клиент id находится в bank_transfers таблице. Я также настоятельно рекомендую FILTER для условной агрегации:

 SELECT bt.date AS day,
       SUM(bt.amount_cents) FILTER (WHERE bt.amount_cents < 0) as sum_expenses,
       SUM(bt.amount_cents) FILTER (WHERE bt.amount_cents > 0) as sum_revenue
FROM bank_transfers bt
WHERE bt.customer_id = 1 AND
      bt.date >= '2020-08-26' AND
      bt.date < '2020-11-26'
GROUP BY DAY;