我有一个名为 ORD_FX 的表,用于存储与外汇交易相关的所有信息。另一个表 ORD_SI 保存有关结算指令的信息。此外,还有一个名为 ORD_CS 的表,其中包含客户信息,ORD_FX (ord_cs.wss_tid = ord_fx.cust_tid) 和 ORD_SI (ord_cs.wss_tid = ord_si.cust_tid) 表中都存在 CUST_TID。 ORD_SI表中的WSS_TID等于ORD_FX表中的FSI_TID或FSI_REC_TID,因为支付方和接收方都需要结算指令。
每当有人向 ORD_SI 表添加新的结算指令 (SI) 时,它就会获得状态“A”(已添加)。如果 ORD_SI 表中的结算指令发生更改,则该结算指令的 WSS_TID 也会发生变化。这会产生类似的 SI,仅进行较小的更改,但具有新的 WSS_TID,并且新 SI 的状态将为“C”(已更改),而旧 SI 仍将具有状态“A”。此过程可以无限期地继续,所有修改的 SI 都会继承状态“C”。
我的任务是查找特定客户的所有活跃 SI,即已预订的交易以及交易者使用活跃 SI 的位置。 SI 可以具有状态“C”,但绝不会附加到交易(未使用)。我需要一个小的开关循环来显示 CUSTOMER_NAME、活动 SI 以及是否使用过。如果使用,它还应该使用 TRADE_DATE 显示上次使用时间(来自 ord_fx)。 ORD_SI 表应该是主表,因为它包含活跃但从未使用过的客户的 SI。我尝试了一些方法,但没有运气。 一个客户可以对同一个 ccy 有多个结算指令。
SELECT
cs.cust_number,
si.wss_tid AS active_si,si.FSI_IDENTIFIER,si.ccy,si.last_chg_type,
CASE
WHEN MAX(fx.trade_date) IS NOT NULL THEN 'Used'
ELSE 'Not Used'
END AS si_status,
MAX(fx.trade_date) AS last_used_date
FROM
ord_cs cs
JOIN
ord_fx fx ON cs.WSS_TID = fx.cust_tid
JOIN
ord_si si ON (si.wss_tid = fx.fsi_tid OR si.wss_tid = fx.fsi_rec_tid)
WHERE
cs.cust_number = 'CUST1'
GROUP BY
cs.cust_number, si.wss_tid,si.FSI_IDENTIFIER,si.ccy,si.last_chg_type
ORDER BY
cs.cust_number, si.wss_tid;
CUST_NUMBER ACTIVE_SI FSI_IDENTIFIER CCY LAST_CHG_TYPE SI_STATUS LAST_USED_DATE
CUST2 202102130002.00 CAD_instruction CAD C Used 8/23/2024 0:00
CUST2 202102130003.00 USD_Instruction USD C Used 8/23/2024 0:00
CUST2 202102130004.00 GBP_Instruction GBP A not used null
CUST2 202102130005.00 GBP_Instruction_1 GBP A used 8/15/2024 0:00
结算指令可以多次使用,因此我使用了最大交易。
以下代码片段为
si.CUST_TID, si.FSI_IDENTIFIER, si.CCY
的每个组合将值 1 分配给“最近”行。请注意,按日期降序排列可确保最近日期的行号为 1。
, ROW_NUMBER() OVER (
PARTITION BY si.CUST_TID, si.FSI_IDENTIFIER, si.CCY
ORDER BY si.LAST_CHG_TYPE DESC
) AS rn
然后在主查询中,您可以使用这些“最近”行将查询限制为仅有效结算指令。然后左键加入外汇交易信息表,因为这将允许识别任何尚未执行的活动指令。
因此,下面使用 CTE 来定位最近的行,主查询使用带有条件
AND si.rn = 1
的内部联接来将结算指令行限制为最新的行。然后,交易信息被左连接,允许在结果中返回空交易日期:
WITH ActiveSI AS (
SELECT si.WSS_TID, si.CUST_TID, si.FSI_IDENTIFIER, si.CCY, si.LAST_CHG_TYPE
, ROW_NUMBER() OVER (
PARTITION BY si.CUST_TID, si.FSI_IDENTIFIER, si.CCY
ORDER BY si.LAST_CHG_TYPE DESC
) AS rn
FROM ORD_SI si
WHERE si.STATUS IN ('A', 'C')
)
SELECT cs.CUSTOMER_NAME
, si.WSS_TID AS active_si
, si.FSI_IDENTIFIER
, si.CCY
, si.LAST_CHG_TYPE
, CASE
WHEN MAX(fx.TRADE_DATE) IS NOT NULL THEN 'Used'
ELSE 'Not Used'
END AS si_status
, MAX(fx.TRADE_DATE) AS last_used_date
FROM ORD_CS cs
INNER JOIN ActiveSI si ON cs.WSS_TID = si.CUST_TID AND si.rn = 1
LEFT JOIN ORD_FX fx ON (
si.WSS_TID = fx.FSI_TID
OR si.WSS_TID = fx.FSI_REC_TID
)
-- optional where clause as needed
GROUP BY cs.CUSTOMER_NAME
, si.WSS_TID
, si.FSI_IDENTIFIER
, si.CCY
, si.LAST_CHG_TYPE
ORDER BY cs.CUSTOMER_NAME
, si.WSS_TID;
假设样本数据:
INSERT INTO ORD_CS VALUES
('C1', 'CUST1', 'Customer 1'),
('C2', 'CUST2', 'Customer 2');
INSERT INTO ORD_FX VALUES
('T1', 'C1', 'SI1', 'SI2', '2024-12-15'),
('T2', 'C1', 'SI3', 'SI4', '2024-12-18'),
('T3', 'C2', 'SI5', 'SI6', '2024-12-20');
INSERT INTO ORD_SI VALUES
('SI1', 'C1', 'FSI001', 'USD', 'C', 'A'),
('SI2', 'C1', 'FSI002', 'EUR', 'A', 'A'),
('SI3', 'C1', 'FSI003', 'GBP', 'C', 'C'),
('SI4', 'C1', 'FSI004', 'JPY', 'A', 'A'),
('SI5', 'C2', 'FSI005', 'AUD', 'C', 'C'),
('SI6', 'C2', 'FSI006', 'CAD', 'A', 'A'),
('SI7', 'C1', 'FSI007', 'CHF', 'A', 'A');
针对该数据的查询结果:
CUSTOMER_NAME | ACTIVE_SI | FSI_IDENTIFIER | CCY | LAST_CHG_TYPE | SI_状态 | 最后使用日期 |
---|---|---|---|---|---|---|
客户1 | SI1 | FSI001 | 美元 | C | 二手 | 24 年 12 月 15 日 |
客户1 | SI2 | FSI002 | 欧元 | A | 二手 | 24 年 12 月 15 日 |
客户1 | SI3 | FSI003 | 英镑 | C | 二手 | 24 年 12 月 18 日 |
客户1 | SI4 | FSI004 | 日元 | A | 二手 | 24 年 12 月 18 日 |
客户1 | SI7 | FSI007 | 瑞士法郎 | A | 未使用 | 空 |
客户2 | SI5 | FSI005 | 澳元 | C | 二手 | 20 年 12 月 24 日 |
客户2 | SI6 | FSI006 | CAD | A | 二手 | 20 年 12 月 24 日 |