-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAnalysis_queries.sql
More file actions
134 lines (123 loc) · 4.58 KB
/
Analysis_queries.sql
File metadata and controls
134 lines (123 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* ===========================================================
FRAUD RISK ANALYSIS - MAIN SQL QUERIES
=========================================================== */
/* 1️⃣ Customer Segmentation & Risk Analysis */
WITH customer_segments AS (
SELECT m.customer_id,
CASE
WHEN MONTHS_BETWEEN(SYSDATE, m.registration_date) < 12 THEN 'New'
WHEN MONTHS_BETWEEN(SYSDATE, m.registration_date) BETWEEN 12 AND 36 THEN 'Mid-term'
ELSE 'Loyal'
END AS customer_segment,
k.card_id,
CASE
WHEN k.credit_limit < 2000 THEN 'Standard'
WHEN k.credit_limit BETWEEN 2000 AND 7500 THEN 'Gold'
ELSE 'Platinum'
END AS card_segment
FROM Musteriler m
JOIN Kartlar k ON m.customer_id = k.customer_id
)
SELECT cs.customer_segment,
cs.card_segment,
COUNT(*) AS total_tx,
SUM(CASE WHEN t.is_fraud = 1 THEN 1 END) AS fraud_tx,
ROUND(SUM(CASE WHEN t.is_fraud = 1 THEN 1 END) * 100.0 / COUNT(*), 2) AS fraud_rate
FROM customer_segments cs
JOIN Tranzaksiyalar t ON cs.card_id = t.card_id
GROUP BY cs.customer_segment, cs.card_segment
ORDER BY cs.customer_segment, cs.card_segment;
/* 2️⃣ Dormant Card – Time Before Fraud */
SELECT
t.card_id,
t.transaction_id,
t.transaction_datetime,
t.is_fraud,
MAX(CASE WHEN is_fraud = 0 THEN transaction_datetime END)
OVER (PARTITION BY card_id ORDER BY transaction_datetime
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
AS last_legit_datetime,
ROUND(
(CAST(t.transaction_datetime AS DATE) -
CAST(MAX(CASE WHEN is_fraud = 0 THEN transaction_datetime END)
OVER (PARTITION BY card_id ORDER BY transaction_datetime
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS DATE))
) AS dormant_days
FROM Tranzaksiyalar t
ORDER BY t.card_id, t.transaction_datetime;
/* 3️⃣ Spending Velocity Anomaly */
SELECT
t.card_id,
t.transaction_id,
t.transaction_datetime,
t.transaction_amount,
t.is_fraud,
SUM(t.transaction_amount) OVER (
PARTITION BY t.card_id
ORDER BY t.transaction_datetime
RANGE BETWEEN INTERVAL '24' HOUR PRECEDING AND CURRENT ROW
) AS rolling_sum_24h,
ROUND(
AVG(t.transaction_amount) OVER (
PARTITION BY t.card_id
ORDER BY t.transaction_datetime
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
), 2
) AS moving_avg_3tx
FROM Tranzaksiyalar t
ORDER BY t.card_id, t.transaction_datetime;
/* 4️⃣ First Attack Analysis – Stolen Cards Only */
WITH FirstFraudAttacks AS (
SELECT *
FROM (
SELECT t.card_id,
t.transaction_id,
t.transaction_datetime,
t.transaction_amount,
ROW_NUMBER() OVER (PARTITION BY t.card_id ORDER BY t.transaction_datetime) AS rn
FROM Tranzaksiyalar t
JOIN Kartlar c ON t.card_id = c.card_id
WHERE t.is_fraud = 1 AND c.card_status = 'Stolen'
)
WHERE rn = 1
)
SELECT
f.card_id,
COUNT(t.transaction_id) AS follow_up_frauds,
SUM(t.transaction_amount) AS total_loss
FROM FirstFraudAttacks f
JOIN Tranzaksiyalar t ON f.card_id = t.card_id
WHERE t.is_fraud = 1
AND t.transaction_datetime BETWEEN f.transaction_datetime
AND f.transaction_datetime + INTERVAL '1' HOUR
GROUP BY f.card_id
ORDER BY f.card_id;
/* 5️⃣ Fraud Chain Mapping – Merchant Hotspots */
SELECT
s.merchant_name,
COUNT(*) AS fraud_count,
COUNT(DISTINCT t.card_id) AS unique_cards
FROM Tranzaksiyalar t
JOIN Saticilar s ON t.merchant_id = s.merchant_id
WHERE t.is_fraud = 1
GROUP BY s.merchant_name, TRUNC(t.transaction_datetime, 'HH24')
HAVING COUNT(DISTINCT t.card_id) > 5
ORDER BY fraud_count DESC;
/* 6️⃣ Smart Limit Rule Simulation */
SELECT
SUM(CASE WHEN t.is_fraud = 1 THEN 1 END) AS true_positive,
SUM(CASE WHEN t.is_fraud = 0 THEN 1 END) AS false_positive,
COUNT(*) AS total_blocked
FROM Tranzaksiyalar t
LEFT JOIN (
SELECT card_id, MAX(transaction_amount) AS max_legit_amount
FROM Tranzaksiyalar
WHERE is_fraud = 0
AND transaction_datetime >= SYSDATE - 30
GROUP BY card_id
) max_tx
ON t.card_id = max_tx.card_id
WHERE t.transaction_amount > 10 * COALESCE(max_tx.max_legit_amount, 0)
AND (UPPER(t.transaction_location) IN ('USA','CHINA','TURKEY')
OR UPPER(t.transaction_location) NOT IN ('BAKI','SUMQAYIT','GƏNCƏ','ŞƏKİ','LƏNKƏRAN',
'MİNGƏÇEVİR','NAXÇIVAN','QUBA','ŞİRVAN','ONLINE'));