MySQL如何编写SQL以在15分钟的窗口中查找过多的事务?

dav*_*jhp 12 mysql sql group-by

MySQL
让我们说有一家信用卡处理公司.每次使用信用卡时,都会将一行插入表格中.

create table tran(
  id int,
  tran_dt datetime, 
  card_id int,
  merchant_id int,
  amount int
);
Run Code Online (Sandbox Code Playgroud)

人们想知道在同一商家的任何15分钟窗口中已经使用了3次以上的卡.

我的尝试:

select card_id, date(tran_dt), hour(tran_dt), merchant_id, count(*)
from tran
group by card_id, date(tran_dt), hour(tran_dt), merchant_id
having count(*)>=3
Run Code Online (Sandbox Code Playgroud)

第一个问题是每小时会产生过多的交易,而不是每15分钟一次.第二个问题是不会捕获跨越小时标记的交易,即下午1:59和下午2:01.

为了使这更简单,可以将小时分成5分钟的增量.所以我们不需要在下午1:00-1:15,下午1:01-1:16等检查.可以在下午1:00-1:15,1:05-1:20等检查,等等,如果那更容易.

任何想法如何修复SQL?我有一种感觉,也许我需要sql窗口函数,这在MySQL中尚不可用.或者编写一个可以查看每个15块的存储过程.

http://sqlfiddle.com/#!9/f2d74/1

Gor*_*off 2

您可以将日期/时间转换为秒,并对秒进行算术以获得 15 分钟时钟间隔内的值:

select card_id, min(date(tran_dt)) as first_charge_time, merchant_id, count(*)
from tran
group by card_id, floor(to_seconds(tran_dt) / (60 * 15)), merchant_id
having count(*) >= 3;
Run Code Online (Sandbox Code Playgroud)

以上使用to_seconds(). 在早期版本的 MySQL 中,您可以使用unix_timestamp().

获得 15 分钟的间歇时间更具挑战性。您可以将查询表达为:

select t1.*, count(*) as numTransactions
from tran t1 join
     tran t2
     on t1.merchant_id = t2.merchanti_d and
        t1.card_id = t2.card_id and
        t2.tran_dt >= t1.tran_dt and
        t2.tran_dt < t1.tran_dt + interval 15 minute 
group by t1.id
having numTransactions >= 3;
Run Code Online (Sandbox Code Playgroud)

此查询的性能可能存在问题。索引trans(card_id, merchant_id, tran_dt)应该会有很大帮助。