Home > Net >  ORACLE SQL. Count sum values larger than 2 millions within 30 days
ORACLE SQL. Count sum values larger than 2 millions within 30 days

Time:03-10

I am trying to find cust_id who made transactions larger than 2 millions within 30 days.

Days are calculated by DATE column.

cust_id ABCD BUY AAA in 2021/10/01 and sell in 2021/10/05, within 4 days, the amt is larger than 2 millions,this is what i want.

cust_id QRST BUY AAA in 2021/10/07 with 900,000 and 100, then sell in 2021/10/07 with 100, within 1 days, but the amt is less than 2 millions, not my result

cust_id ZZYY BUY CCC with 1,000,000 in 2021/10/08 and sell with 1,000,000 in 2021/12/07, amt larger than 2,000,000 but buy date to sell date is longer than 30 days, not my result

CUST_ID AMT DATE PRD_ID TRAN
ABCD 1,000,000 2021/10/01 AAA BUY
ABCD 1,000,000 2021/10/05 AAA SELL
ABCD 1,000,000 2021/10/06 BBB BUY
QRST 900,000 2021/10/07 AAA BUY
QRST 100 2021/10/07 AAA BUY
QRST 100 2021/10/07 AAA SELL
ZZYY 1,000,000 2021/10/08 CCC BUY
ZZYY 1,000,000 2021/12/07 CCC SELL

what i want is

CUST_ID AMT DATE PRD_ID
ABCD 1,000,000 2021/10/01 AAA
ABCD 1,000,000 2021/10/05 AAA

CodePudding user response:

From Oracle 12, you can find values that are within a 30-day rolling window using MATCH_RECOGNIZE:

SELECT cust_id,
       amt,
       "DATE",
       prd_id,
       tran,
       match_number
FROM   table_name
MATCH_RECOGNIZE(
  PARTITION BY cust_id, prd_id
  ORDER     BY "DATE"
  MEASURES
    MATCH_NUMBER() AS match_number
  ALL ROWS PER MATCH
  AFTER MATCH SKIP TO NEXT ROW
  PATTERN (within_30_days* over_2m)
  DEFINE
    within_30_days AS "DATE" <= FIRST("DATE")   INTERVAL '30' DAY,
    over_2m        AS "DATE" <= FIRST("DATE")   INTERVAL '30' DAY
                      AND SUM(amt) >= 2000000
)

Which, for the sample data:

CREATE TABLE table_name (CUST_ID, AMT, "DATE", PRD_ID, TRAN) AS
SELECT 'ABCD', 1000000, DATE '2021-10-01', 'AAA', 'BUY'  FROM DUAL UNION ALL
SELECT 'ABCD', 1000000, DATE '2021-10-05', 'AAA', 'SELL' FROM DUAL UNION ALL
SELECT 'ABCD', 1000000, DATE '2021-10-06', 'BBB', 'BUY'  FROM DUAL UNION ALL
SELECT 'QRST',  900000, DATE '2021-10-07', 'AAA', 'BUY'  FROM DUAL UNION ALL
SELECT 'QRST',     100, DATE '2021-10-07', 'AAA', 'BUY'  FROM DUAL UNION ALL
SELECT 'QRST',     100, DATE '2021-10-07', 'AAA', 'SELL' FROM DUAL UNION ALL
SELECT 'ZZYY', 1000000, DATE '2021-10-08', 'CCC', 'BUY'  FROM DUAL UNION ALL
SELECT 'ZZYY', 1000000, DATE '2021-12-07', 'CCC', 'SELL' FROM DUAL;

Outputs:

CUST_ID AMT DATE PRD_ID TRAN MATCH_NUMBER
ABCD 1000000 01-OCT-21 AAA BUY 1
ABCD 1000000 05-OCT-21 AAA SELL 1

db<>fiddle here

CodePudding user response:

You updated the question later. Hence, I am answering again based upon more information.

WITH buy_date AS (
    SELECT
        b.cust_id,
        b.date,
        b.prd_id
    FROM
        table_name b
    WHERE
            b.tran = 'BUY'
        AND b.amt > 2000000
), sell_date AS (
    SELECT
        s.cust_id,
        s.date,
        s.prd_id
    FROM
        table_name s
    WHERE
            s.tran = 'SELL'
        AND s.amt > 2000000
)
SELECT
    *
FROM
    buy_date   bd,
    sell_date  sd
WHERE
        bd.cust_id = sd.cust_id
    AND bd.prd_id = sd.prd_id
    AND sd.date - bd.date <= 30;
  • Related