gpt4 book ai didi

oracle - 有趣的 Oracle 分析查询挑战

转载 作者:行者123 更新时间:2023-12-04 15:03:05 26 4
gpt4 key购买 nike

我对 Oracle 分析功能相当有经验,但这让我很难过。如果有明显的解决方案,我会踢自己:)

我有一个表 JOURNAL,它记录另一个表上的插入、更新和删除。

它的日记帐表是 BOND_PAYMENTS,它表示 PAYMENTS 和 BONDS 之间的链接;它存储从特定付款(由 PAYMENT_ID 标识)分配给特定债券(由 BOND_NUMBER 标识)的金额(AMOUNT)。此外,它还记录了它被分配给 (BOP_DOMAIN) 的债券的哪个方面,可能是“BON”、“PET”或其他一些代码。 BOND_PAYMENTS 表有一个代理键 (BOP_ID)。

因此,我的日志表通常会为每个 BOP_ID 包含 1 个或多个记录 - 首先是一个插入,然后可能是一些更新,然后可能是一个删除。

这是 JOURNAL 表:

CREATE TABLE JOURNAL
( JN_DATE_TIME DATE NOT NULL,
JN_OPERATION VARCHAR2(3) NOT NULL,
BOP_ID NUMBER(9) NOT NULL,
PAYMENT_ID NUMBER(9) NOT NULL,
BOND_NUMBER VARCHAR2(20) NOT NULL,
BOP_DOMAIN VARCHAR2(10) NOT NULL,
AMOUNT NUMBER(14,2) NOT NULL
);

以下是一些示例数据:
INSERT INTO JOURNAL VALUES (TO_DATE('01/01/2010','DD/MM/YYYY'),'INS',1242043,1003700,'9995/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('03/01/2010','DD/MM/YYYY'),'INS',1242046,1003700,'9998/10','BON',1700);
INSERT INTO JOURNAL VALUES (TO_DATE('04/01/2010','DD/MM/YYYY'),'INS',1242048,1003700,'9999/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('05/01/2010','DD/MM/YYYY'),'INS',1242052,1003700,'10003/10','BON',1600);
INSERT INTO JOURNAL VALUES (TO_DATE('08/01/2010','DD/MM/YYYY'),'INS',1242058,1003700,'9998/10','BON',100);
INSERT INTO JOURNAL VALUES (TO_DATE('09/01/2010','DD/MM/YYYY'),'UPD',1242058,1003700,'9998/10','PET',100);
INSERT INTO JOURNAL VALUES (TO_DATE('01/01/2010','DD/MM/YYYY'),'INS',2242043,1003701,'8995/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('02/01/2010','DD/MM/YYYY'),'INS',2242046,1003701,'8998/10','BON',1700);
INSERT INTO JOURNAL VALUES (TO_DATE('03/01/2010','DD/MM/YYYY'),'INS',2242048,1003701,'8999/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('04/01/2010','DD/MM/YYYY'),'INS',2242058,1003701,'8998/10','BON',100);
INSERT INTO JOURNAL VALUES (TO_DATE('05/01/2010','DD/MM/YYYY'),'UPD',2242046,1003701,'8998/10','BON',1500);
INSERT INTO JOURNAL VALUES (TO_DATE('06/01/2010','DD/MM/YYYY'),'INS',2242052,1003701,'9003/10','BON',1600);
INSERT INTO JOURNAL VALUES (TO_DATE('07/01/2010','DD/MM/YYYY'),'UPD',2242058,1003701,'8998/10','PET',200);

现在,我需要从这个日志表中提取一整套数据,但格式略有不同。主要要求是我们不希望日志表再记录 BOP_DOMAIN - 这不是必需的。

我需要为每个 BOND_PAYMENT 记录生成总金额的历史记录。我不能使用 BOND_PAYMENT 表本身,因为它只显示每条记录的最新状态。我需要从日志中挖掘这些信息。

我不能只拿一个 SUM(amount) over(partition by payment_id, bond_number)因为单个 BOP_ID 可能会更新多次;所以在任何时候,只应使用为该 BOP_ID 记录的最新金额。

鉴于上述示例数据,以下是我期望产生的说明:
SELECT jn_date_time,
jn_operation,
bop_id,
payment_id,
bond_number,
bop_domain,
amount,
? as running_total
FROM JOURNAL
ORDER BY jn_date_time;

sample data and expected results

在这里,我在左侧复制了样本数据,用于两个样本付款。在右边,我有“Running Total”,这是预期的输出。旁边(红色)是它如何计算每行的运行总数的逻辑。

“运行总计”是在日记帐分录的时间点,PAYMENT_ID 和 BOND_NUMBER 组合的总金额的快照。请记住,特定的 BOP_ID 可能会更新多次;总金额必须仅考虑该 BOP_ID 的最新记录。

任何可行的解决方案都是可以接受的,但我怀疑分析函数(或分析函数的组合)将是解决此问题的最佳方法。

最佳答案

尝试这个

WITH inner AS  
(SELECT jn_date_time,
jn_operation,
bop_id,
payment_id,
bond_number,
bop_domain,
amount,
amount - coalesce(lag(amount) over (partition by bop_id order by jn_date_time), 0)
as delta_bop_amount
FROM JOURNAL)
SELECT inner.*,
sum(delta_bop_amount)
over (partition by payment_id, bond_number order by jn_date_time) as running_total
FROM inner
ORDER BY bond_number, payment_id

这将为您的示例返回相同的答案。

您需要两次传递 - 内部查询中的分析函数计算出每条记录对每个 BOP_ID 的总更改量。 INS 是直接添加,UPD 必须减去最近的值并添加新值。

然后第二遍通过债券/付款进行总计。

我假设您想将债券/付款视为流水账的自然键,并且任何债券/付款组合都可能有多个 BOP_ID。

关于oracle - 有趣的 Oracle 分析查询挑战,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8350891/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com