Вы можете использовать предложение WITH
, также называемое "общим табличным выражением" или "CTE", чтобы разбить вашу проблему на управляемые куски.
Вот один из способов сделать это:
WITH txn_by_date AS (
SELECT t.account_key,
t.txn_date,
tt.transaction_type,
sum(t.amount) amount
FROM txns t
INNER JOIN txn_types tt on tt.transaction_key = t.transaction_key
GROUP BY t.account_key, t.txn_date, tt.transaction_type )
SELECT tin.account_key,
tin.txn_date,
tin.amount amount_in,
tout.txn_date,
tout.amount amount_out,
tin.amount / tout.amount ratio
FROM txn_by_date tin
INNER JOIN txn_by_date tout ON tout.txn_date = tin.txn_date + 1
AND tout.transaction_type = 'out'
AND tout.account_key = tin.account_key
WHERE tin.transaction_type = 'in';
Сначала CTE вычисляет общую сумму txn по счету, типу транзакции и дню.Как только у вас есть это, основной SELECT
получает каждое итоговое значение «в», объединяет его с итоговым «выходным» числом подряд и вычисляет соотношение.
Вот полный пример с тестомданные (также выражаются с помощью предложения WITH
):
with txns (account_key, Transaction_key, txn_date, amount) AS
(
SELECT 1, 11, TO_DATE('03/22/2019','MM/DD/YYYY'), 5000 FROM DUAL UNION ALL
SELECT 1, 12, TO_DATE('03/23/2019','MM/DD/YYYY'), 6000 FROM DUAL UNION ALL
SELECT 1, 13, TO_DATE('03/22/2019','MM/DD/YYYY'), 4000 FROM DUAL UNION ALL
SELECT 1, 14, TO_DATE('03/23/2019','MM/DD/YYYY'), 3000 FROM DUAL ),
txn_types ( transaction_key, transaction_type ) AS
(
SELECT 11, 'in' FROM DUAL UNION ALL
SELECT 12, 'out' FROM DUAL UNION ALL
SELECT 13, 'in' FROM DUAL UNION ALL
SELECT 14, 'out' FROM DUAL ),
txn_by_date AS (
SELECT t.account_key,
t.txn_date,
tt.transaction_type,
sum(t.amount) amount
FROM txns t
INNER JOIN txn_types tt on tt.transaction_key = t.transaction_key
GROUP BY t.account_key, t.txn_date, tt.transaction_type )
SELECT tin.account_key,
tin.txn_date,
tin.amount amount_in,
tout.txn_date,
tout.amount amount_out,
tin.amount / tout.amount ratio
FROM txn_by_date tin
INNER JOIN txn_by_date tout ON tout.txn_date = tin.txn_date + 1
AND tout.transaction_type = 'out'
AND tout.account_key = tin.account_key
WHERE tin.transaction_type = 'in';
+-------------+-----------+-----------+------------+------------+-------+
| ACCOUNT_KEY | TXN_DATE | AMOUNT_IN | TXN_DATE_1 | AMOUNT_OUT | RATIO |
+-------------+-----------+-----------+------------+------------+-------+
| 1 | 22-MAR-19 | 9000 | 23-MAR-19 | 9000 | 1 |
+-------------+-----------+-----------+------------+------------+-------+
Альтернативная версия, для древних версий ORACLE
Для действительно старых версий Oracleвам, возможно, придется избегать как предложения WITH
, так и соединений в стиле ANSI.Вот вышеупомянутый запрос, переписанный, чтобы избежать этих функций.
SELECT tin.account_key,
tin.txn_date,
tin.amount amount_in,
tout.txn_date,
tout.amount amount_out,
tin.amount / tout.amount ratio
FROM ( SELECT t.account_key,
t.txn_date,
tt.transaction_type,
sum(t.amount) amount
FROM txns t,
txn_types tt
WHERE tt.transaction_key = t.transaction_key
GROUP BY t.account_key, t.txn_date, tt.transaction_type ) tin,
( SELECT t.account_key,
t.txn_date,
tt.transaction_type,
sum(t.amount) amount
FROM txns t,
txn_types tt
WHERE tt.transaction_key = t.transaction_key
GROUP BY t.account_key, t.txn_date, tt.transaction_type ) tout
WHERE tin.transaction_type = 'in'
AND tout.transaction_type(+) = 'out'
AND tout.account_key(+) = tin.account_key;