我有客户,他们有多个账户。每个账户我都有一个单独的余额。
正如你可以看到下面我可以产生一个详细的每日总结每个帐户。什么是将这个细节 Package 到一个函数中的最佳方法,该函数只返回帐户的最终余额?
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
CREATE TABLE CUSTOMERS (
CUSTOMER_ID, FIRST_NAME, LAST_NAME,IS_ACTIVE) AS
SELECT 'A355135', 'Otto', 'Vatsch','Y' FROM DUAL UNION ALL
SELECT 'B375480', 'Sophia', 'Fazio','Y' FROM DUAL UNION ALL
SELECT 'C378853', 'Brian', 'Vendome','Y' FROM DUAL UNION ALL
SELECT 'D379171', 'John', 'Carucci','Y' FROM DUAL UNION ALL
SELECT 'E379466', 'Bonnie', 'Winterbottom','Y' FROM DUAL UNION ALL
SELECT 'F379739', 'Debra', 'Caygle','Y' FROM DUAL UNION ALL
SELECT 'G379994', 'Jerry', 'Torciano','Y' FROM DUAL UNION ALL
SELECT 'H380235', 'Karl', 'Malden','Y' FROM DUAL UNION ALL
SELECT 'I380492', 'Joseph', 'Zaza','Y' FROM DUAL UNION ALL
SELECT 'J380753', 'Tom', 'Micelli','Y' FROM DUAL UNION ALL
SELECT 'K380989', 'Lisa', 'Saladino','Y' FROM DUAL UNION ALL
SELECT 'L381307', 'Jeff', 'Lebowitz','Y' FROM DUAL UNION ALL
SELECT 'M381569', 'Brian', 'Zanona','Y' FROM DUAL UNION ALL
SELECT 'N381823', 'Seth', 'Bobet','Y' FROM DUAL UNION ALL
SELECT 'O382059', 'Mitch', 'Weinreb','Y' FROM DUAL UNION ALL
SELECT 'P382319', 'Roz', 'Stern','Y' FROM DUAL UNION ALL
SELECT 'Q382564', 'Zoey', 'Zanzone','Y' FROM DUAL UNION ALL
SELECT 'R382815', 'Diane', 'Stein','Y' FROM DUAL UNION ALL
SELECT 'S441015', 'Tony', 'Dimeo','Y' FROM DUAL UNION ALL
SELECT 'T441333', 'Faith', 'Carrucci','Y' FROM DUAL UNION ALL
SELECT 'X098533', 'Brian', 'Tessio','Y' FROM DUAL UNION ALL
SELECT 'Y098273', 'Cheryl', 'Brasi','Y' FROM DUAL UNION ALL
SELECT 'Z098555', 'Peter', 'Clemenza','Y' FROM DUAL;
CREATE TABLE CUSTOMER_ACCOUNTS (
ACCOUNT_NUMBER,
CUSTOMER_ID, VENDOR_ID,
IS_ACTIVE) AS
SELECT 'B17ARWYYZRCU2Q2',
'D379171', 8, 'Y' FROM DUAL UNION ALL
SELECT '0T81Z07CS6LXQ7Z',
'D379171', 7, 'Y' FROM DUAL UNION ALL
SELECT 'YWYXC3Q5N9XZ7S',
'D379171', 7, 'Y' FROM DUAL UNION ALL
SELECT '612ZKAQ66VA3W3',
'D379171', 4, 'Y' FROM DUAL UNION ALL
SELECT 'THVQD6M9LR7AVK', 'E379466', 5, 'Y' FROM DUAL UNION ALL
SELECT 'CFM9K06ZR98R9H2', 'K380989', 1, 'Y' FROM DUAL UNION ALL
SELECT '0Z8NQN6JZRZWFPX',
'K380989', 2, 'Y' FROM DUAL UNION ALL
SELECT 'BCHD9TW78W67S1D',
'K380989', 3, 'Y' FROM DUAL UNION ALL
SELECT '01SUV1Y3BJTCFXY',
'X098533', 1, 'Y' FROM DUAL UNION ALL
SELECT 'TAJ3N5EB9ZX7AD',
'X098533', 2, 'Y' FROM DUAL UNION ALL
SELECT 'Y88JTBCP8SUFY8',
'X098533', 3, 'Y' FROM DUAL UNION ALL
SELECT '06LP3CYJLS01F2L',
'Y098273', 7, 'Y' FROM DUAL UNION ALL
SELECT 'TFWVBRC5QHQLC4', 'Y098273', 8, 'Y' FROM DUAL UNION ALL
SELECT '0Z76WT5NTLRZPTW', 'Z098555', 10, 'Y' FROM DUAL;
create table transactions (
transaction_id NUMBER GENERATED BY DEFAULT AS IDENTITY,
account_number VARCHAR2(15),
transaction_type varchar2(1),
transaction_amount NUMBER(10,2),
transaction_date DATE
);
insert into transactions(
account_number, transaction_type, transaction_amount, transaction_date)
SELECT '0Z8NQN6JZRZWFPX', 'D', 1000 * LEVEL, date '2023-03-29' + level * interval '2' day from dual
connect by level <= 3
union all
SELECT '0Z8NQN6JZRZWFPX', 'C', 500 * LEVEL, date '2023-03-30' + level * interval '2' day from dual
connect by level <= 2
WITH daily_summary AS
(
SELECT
account_number,
transaction_date
, SUM (DECODE (transaction_type, 'C', transaction_amount, 0)) AS credit_total
, SUM (DECODE (transaction_type, 'D', transaction_amount , 0)) AS debit_total
FROM transactions
GROUP BY account_number, transaction_date
)
SELECT d.*
, SUM (debit_total - credit_total)
OVER (ORDER BY transaction_date) AS balance_to_date
FROM daily_summary d
WHERE account_number ='0Z8NQN6JZRZWFPX'
ORDER BY transaction_date;
ACCOUNT_NUMBER TRANSACTION_DATE CREDIT_TOTAL DEBIT_TOTAL BALANCE_TO_DATE
0Z8NQN6JZRZWFPX 31-MAR-2023 00:00:00 0 1000 1000
0Z8NQN6JZRZWFPX 01-APR-2023 00:00:00 500 0 500
0Z8NQN6JZRZWFPX 02-APR-2023 00:00:00 0 2000 2500
0Z8NQN6JZRZWFPX 03-APR-2023 00:00:00 1000 0 1500
0Z8NQN6JZRZWFPX 04-APR-2023 00:00:00 0 3000 4500
希望传入帐号并生成此输出。
SELECT
CA.ACCOUNT_NUMBER,
C.FIRST_NAME,
C.LAST_NAME,
CA.IS_ACTIVE,
Get_Acccount_Balance('0Z8NQN6JZRZWFPX')
FROM CUSTOMER_ACCOUNTS CA
JOIN customers c ON ca.customer_id = c.customer_id
ACCOUNT_NUMBER FIRST_NAME LAST_NAME IS_ACTIVE BALANCE
0Z8NQN6JZRZWFPX Lisa Saladino Y 4500
注:如果贷方总额高于余额,则余额可能为负数。
2条答案
按热度按时间k2fxgqgv1#
你不需要一个函数(这将涉及SQL和PL/SQL之间的上下文切换,并且可能会更慢)。
相反,您可以在SQL中完成所有操作并使用相关子查询:
或者,从Oracle 12,
LATERAL
连接:对于您的示例数据,两者都输出:
| 联系我们|公司简介|激活|平衡| BALANCE |
| - -----|- -----|- -----|- -----| ------------ |
| 约翰|卡鲁奇|Y轴|联系我们| null |
| 约翰|卡鲁奇|Y轴|联系我们| null |
| 约翰|卡鲁奇|Y轴|联系我们| null |
| 约翰|卡鲁奇|Y轴|联系我们| null |
| 邦妮|温特伯顿|Y轴|联系我们| null |
| 丽莎|萨拉迪诺|Y轴|联系我们| null |
| 丽莎|萨拉迪诺|Y轴|四千五| 4500 |
| 丽莎|萨拉迪诺|Y轴|联系我们| null |
| 布莱恩|泰西奥|Y轴|联系我们| null |
| 布莱恩|泰西奥|Y轴|联系我们| null |
| 布莱恩|泰西奥|Y轴|联系我们| null |
| 谢丽尔|布拉西|Y轴|联系我们| null |
| 谢丽尔|布拉西|Y轴|联系我们| null |
| 彼得|克莱门扎|Y轴|联系我们| null |
如果你确实需要一个函数,那么你可以将子查询的代码 Package 在一个函数中(也许还可以添加
SQL_MACRO(SCALAR)
)。或:
fiddle
t5fffqht2#
你不需要一个函数。构建一个进行聚合的视图并重用它。您还可以使用
JOIN
查询的MERGE
提示将过滤器“推送”到这个非常简单的视图中(或者,如果示例中启用了复杂视图合并,数据库可能会自动执行此操作)。WHERE
过滤器会自动推送。transactions
表中的数据比问题中的数据多:| 客户ID|供应商ID|激活|至今余额| BALANCE_TO_DATE |
| - -----|- -----|- -----|- -----| ------------ |
| D379171|八|Y轴|0| 0 |
| D379171|七个|Y轴|0| 0 |
| D379171|七个|Y轴|0| 0 |
| D379171| 4| Y轴|0| 0 |
| E379466| 5个|Y轴|0| 0 |
| K380989|一个|Y轴|0| 0 |
| K380989| 2| Y轴|四千五| 4500 |
| K380989|三个|Y轴|0| 0 |
| X098533|一个|Y轴|0| 0 |
| X098533| 2| Y轴|0| 0 |
| X098533|三个|Y轴|0| 0 |
| Y098273|七个|Y轴|0| 0 |
| Y098273|八|Y轴|六千| 6000 |
| Z098555|十个|Y轴|0| 0 |
fiddle
如果您还需要特定日期的余额,那么
SQL_MACRO
可能是在查询中推送日期过滤器并避免上下文切换的更好选择。