ELSE 0
>
END) year_2003,
>
SUM(CASE
>
WHEN EXTRACT(YEAR FROM open_date) = 2004 THEN 1
>
ELSE 0
>
END) year_2004,
>
SUM(CASE
>
WHEN EXTRACT(YEAR FROM open_date) = 2005 THEN 1
>
ELSE 0
>
END) year_2005
>
FROM account
>
WHERE open_date > '19991231';
+++++++
| year_2000 | year_2001 | year_2002 | year_2003 | year_2004 | year_2005 |
+++++++
| 3 | 4 | 5 | 3 | 9 | 0 |
+++++++
1 row in set (0.01 sec)
Все шесть выражений для столбцов предыдущего запроса идентичны,
за исключением значения года. Когда функция
extract()
возвращает
нужный год, выражение
case
возвращает значение
1
. В противном слу
чае возвращается
0
. Суммируя все счета, открытые с 2000 года, каж
дый столбец возвращает число счетов, открытых в соответствующий
год. Очевидно, что такие трансформации практически применимы
только для небольшого числа значений. Решение задачи по формиро
ванию столбцов для каждого года, начиная с 1905го, быстро стало бы
слишком громоздким.
Селективная агрегация
Ранее в главе 9 было показано частичное решение задачи поиска сче
тов, остаток на которых не соответствует данным таблицы
transaction
.
Причиной предоставления частичного решения была необходимость
применения условной логики, но теперь у нас есть все для того, чтобы
закончить работу. Вот на чем я остановился в главе 9:
Примеры выражений case
223
SELECT CONCAT('ALERT! : Account #', a.account_id,
' Has Incorrect Balance!')
FROM account a
WHERE (a.avail_balance, a.pending_balance) <>
(SELECT SUM(),
SUM()
FROM transaction t
WHERE t.account_id = a.account_id);
Для суммирования отдельных транзакций по данному счету этот за
прос использует связанный подзапрос к таблице
transaction
. При сум
мировании транзакций следует учитывать два факта:
•
Суммы транзакций всегда положительны, поэтому чтобы понять,
является ли транзакция дебетовой или кредитовой, необходимо по
смотреть на ее тип и изменить знак (умножить на
–
1) для дебетовых
транзакций.
•
Если дата в столбце
funds_avail_date
больше текущей, транзакция
должна быть добавлена в суммарный отложенный остаток, а не
в суммарный доступный остаток.
Из доступного остатка некоторые транзакции должны быть исключе
ны, а в отложенный остаток включаются все транзакции, что делает
его более простым для вычисления. Вот выражение
case
для вычисле
ния отложенного остатка:
CASE
WHEN transaction.txn_type_cd = 'DBT'
THEN transaction.amount * 1
ELSE transaction.amount
END
Таким образом, все суммы транзакций для дебетовых транзакций ум
ножаются на
–
1, а для кредитовых транзакций остаются неизменны
ми. Точно такая же логика применяется и к вычислению доступного
остатка, но здесь должны быть включены только те транзакции, кото
рые стали доступными. Поэтому выражение
case
для вычисления дос
тупного остатка включает один дополнительный блок
when
:
CASE
WHEN transaction.funds_avail_date > CURRENT_TIMESTAMP()
THEN 0
WHEN transaction.txn_type_cd = 'DBT'
THEN transaction.amount * 1
ELSE transaction.amount
END
В первом блоке
when
недоступные фонды, такие как неоплаченные че
ки, будут добавлять к сумме 0 долларов. Вот окончательный вариант
запроса с двумя выражениями
case
:
SELECT CONCAT('ALERT! : Account #', a.account_id,
' Has Incorrect Balance!')
224
Достарыңызбен бөлісу: |