I have a table TRANSACTIONS with almost 30 million transactions (13 COLUMNS). How Can I optimize following code? I tried with self join but it seemed to be less effective.
Logic: I want to get last transactions by sender-receiver_2 if receiver_2 exists, else by sender-receiver + calculate some statistics (10/30/90 days)
SELECT T.* FROM
(SELECT T.*, row_number() over (partition by T.SENDER, (CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END) order by T.DATE_ACCEPT desc) as seqnum
FROM
(
SELECT T.*
,(SELECT COUNT(DISTINCT T2.ID_TRAN)
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 10 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
) CNT_10
,(SELECT COUNT(DISTINCT T2.ID_TRAN)
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 30 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
) CNT_30
,(SELECT COUNT(DISTINCT T2.ID_TRAN)
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 90 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
) CNT_90
,(SELECT DISTINCT AVG(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END) OVER()
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 10 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
GROUP BY T2.ID_TRAN, (CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END)
) AVG_AMOUNT_10
,(SELECT DISTINCT AVG(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END) OVER()
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 30 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
GROUP BY T2.ID_TRAN, (CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END)
) AVG_AMOUNT_30
,(SELECT DISTINCT AVG(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END) OVER()
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 90 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
GROUP BY T2.ID_TRAN, (CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END)
) AVG_AMOUNT_90
,(SELECT MAX(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END)
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 10 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
) MAX_AMOUNT_10
,(SELECT MAX(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END)
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 30 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
) MAX_AMOUNT_30
,(SELECT MAX(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.AMOUNT ELSE T2.AMOUNT_2 END)
FROM TRANSACTIONS T2
WHERE T2.DATE_ACCEPT > T.DATE_ACCEPT - 90 AND
T2.DATE_ACCEPT < T.DATE_ACCEPT AND
(CASE WHEN T.RECEIVER_2 IS NULL THEN T2.RECEIVER ELSE T2.RECEIVER_2 END) =
(CASE WHEN T.RECEIVER_2 IS NULL THEN T.RECEIVER ELSE T.RECEIVER_2 END)
AND
T2.SENDER = T.SENDER
) MAX_AMOUNT_90
FROM TRANSACTIONS T
) T ) T
WHERE T.SEQNUM = 1
Also I created index on (SENDER, DATE_ACCEPT).