SQL против мошенников Интересная статья про паттерны, по которым можно выявить случаи мошенничества и подозрительной активности на банковских счетах с помощью простого ~~советского~~ SQL. Большинство признаков, на которые надо обращать внимание, известны или интуитивно понятны, но автор еще и сами SQL-запросы показывает, и это уже может пригодиться. 🔵Скорость снятия денег. Большое количество операций за короткий срок говорит о том, что мошенник пытается поскорее опустошить карту, пока владелец не заметил. 🔵Телепортация — в течение небольшого промежутка времени карта использовалась в двух местах, между которыми физически невозможно переместиться с такой скоростью. 🔵Снятия подозрительных сумм. Небольшие, круглые суммы — у автор это 1-5-10 долларов — говорят о том, что мошенник проверяет, работает ли карта. Сомнения должны вызывать и частые покупки на суммы ниже пределов, после которых требуется подтверждение личности или пин-код. 🔵Внезапный рост числа уникальных карт у одного мерчанта. Если раньше через него проходили 200 карт в день, а потом их число подскочило до 1000+, это повод присмотреться к нему повнимательнее. 🔵Операции в нетипичное для пользователя время. Например, если человек всегда платит днем, а потом внезапно начинает активно пользоваться картой в 3 ночи. Чтобы выявлять все эти сигналы было проще, автор предлагает заранее материализовать их с помощью оконных функций: ```SELECT cardholder_id, timestamp, amount, merchant_id, timestamp - LAG(timestamp) OVER w AS time_since_last, CASE WHEN merchant_id <> LAG(merchant_id) OVER w THEN 'changed' ELSE 'same' END AS merchant_change, sum(amount) OVER ( PARTITION BY cardholder_id ORDER BY timestamp RANGE BETWEEN INTERVAL '24 hours' PRECEDING AND CURRENT ROW ) AS running_24h_total, ROW_NUMBER() OVER ( PARTITION BY cardholder_id, date(timestamp) ORDER BY timestamp ) AS tx_of_day FROM transactions WINDOW w AS (PARTITION BY cardholder_id ORDER BY timestamp) ORDER BY cardholder_id, timestamp;``` И после этого уже прогонять проверки с помощью WHERE: ```SELECT * FROM tx_with_windows WHERE tx_of_day >= 5 AND time_since_last < INTERVAL '60 seconds' AND merchant_change = 'changed';``` Главное — не переусердствовать и помнить, что каждый сигнал по отдельности, как правило, ничего не доказывает: и обычному человеку может понадобиться снять деньги с карты несколько раз подряд или сбегать в магазин посреди ночи. Чтобы отсеять честных пользователей от мошенников, нужно смотреть на несколько параметров в совокупности.