我有下表USERID、EOMONTH、Pending和cleared是实际的列。 Overdue_Balance 和 Overdue_since_date 是我需要导出的列。
我需要累计计算每个 EOMONTH 的 overdue_balance= sum(pending) - sum(Cleared) 以获得每个 EOMONTH 的 Overdue_Balance。如果存在任何 Overdue_balance,那么当存在 Overdue_balance 时,我需要将 Overdue_since_date 导出为 EOMONTH,并继续相同的 OVerdue_since_date 直到余额变为零。
下面是我尝试过的 SQL 查询 Overdue_Balance 正常出现,但 Overdue_since_date 没有按照我的要求出现,需要使用 SQL 帮助解决它
-- Create a table to store the sample data
CREATE TABLE sample_data (
UserID integer,
EOMONTH date,
Pending integer,
Cleared integer
);
-- Insert sample data into the table
INSERT INTO sample_data (UserID, EOMONTH, Pending, Cleared)
VALUES
(1, '2024-05-31', 50, 110),
(1, '2024-04-30', 100, 100),
(1, '2024-03-31', 50, 0),
(1, '2024-02-29', 50, 40),
(1, '2024-01-31', 100, 100),
(1, '2023-12-31', 50, 70),
(1, '2023-11-30', 90, 80),
(1, '2023-10-31', 100, 90);
-- Display the inserted data
WITH CumulativeSums AS (
SELECT
UserID,
EOMONTH,
Pending,
Cleared,
SUM(Pending - Cleared) OVER (PARTITION BY UserID ORDER BY EOMONTH) AS Overdue_balance,
CASE
WHEN Pending - Cleared < 0 THEN EOMONTH
ELSE NULL
END AS Overdue_since_date_flag
FROM
sample_data
),
ResetPoints AS (
SELECT
UserID,
EOMONTH,
Overdue_since_date_flag,
LAG(Overdue_since_date_flag) OVER (PARTITION BY UserID ORDER BY EOMONTH) AS prev_flag
FROM
CumulativeSums
)
SELECT
UserID,
EOMONTH,
Pending,
Cleared,
CASE
WHEN Overdue_balance < 0 THEN COALESCE(MAX(Overdue_since_date_flag) OVER (PARTITION BY UserID ORDER BY EOMONTH ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), EOMONTH)
WHEN Overdue_balance >= 0 AND LAG(Overdue_balance) OVER (PARTITION BY UserID ORDER BY EOMONTH) < 0 THEN NULL
ELSE COALESCE(MAX(Overdue_since_date_flag) OVER (PARTITION BY UserID ORDER BY EOMONTH ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), EOMONTH)
END AS Overdue_since_date,
Overdue_balance
FROM
CumulativeSums
ORDER BY
UserID, EOMONTH;
您必须检测平衡 > 0 和不平衡 > 0 的行之间的破裂,以便能够通过间隙和岛屿分配组号,然后使用 first_value() 分析您将获得正确的日期:
SELECT d.userid, eomonth, pending, cleared, balance, CASE WHEN balance > 0 THEN
FIRST_VALUE(eomonth) OVER(PARTITION BY UserID, grp ORDER BY eomonth) END AS since
FROM (
SELECT d.*, SUM(rupt) OVER(PARTITION BY UserID ORDER BY eomonth) AS grp
FROM (
SELECT d.*,
CASE WHEN GREATEST(0,sign(LAG(balance,1,0) OVER(PARTITION BY UserID ORDER BY EOMONTH)))
= GREATEST(0,sign(balance)) THEN 0 ELSE 1 END AS rupt
FROM (
SELECT d.*, SUM(Pending - cleared) OVER(PARTITION BY UserID ORDER BY eomonth) AS balance
FROM sample_data d
) d
) d
)
d
ORDER BY eomonth desc
;