如何仅使用最后一个事务来计算timediff mysql 5.7

问题描述

这是find out time difference for every user in condition mysql 5.7

的继续问题

这是我的小提琴 https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=31b3be9d1e2444eb0b32c262176aa4b4

我有这张桌子

CREATE TABLE test (
  ID INT,user_id INT,createdAt DATE,status_id INT
);

INSERT INTO test VALUES
  (1,13,'2020-01-01',8),(2,'2020-01-03',(3,'2020-01-06',(4,'2020-01-02',7),(5,(6,14,'2020-03-03',(7,'2020-03-04',4),(8,15,'2020-04-04',(9,'2020-03-02',6),(10,'2020-03-10',5),(11,'2020-04-10',8);
  
select * from test where status_id != 7
order by createdAt;


+----+---------+------------+-----------+
| ID | user_id | createdAt  | status_id |
+----+---------+------------+-----------+
|  1 |      13 | 2020-01-01 |         8 |
|  2 |      13 | 2020-01-03 |         8 |
|  3 |      13 | 2020-01-06 |         8 |
|  9 |      14 | 2020-03-02 |         6 |
|  6 |      14 | 2020-03-03 |         8 |
|  7 |      13 | 2020-03-04 |         4 |
| 10 |      14 | 2020-03-10 |         5 |
+----+---------+------------+-----------+

id是交易的ID,user_Id是进行交易的用户的ID,createdAt是交易发生的日期,status_id是交易的状态(如果status_Id为7,则拒绝交易或未批准)。

因此,在这种情况下,我想找出每个重复用户在'2020-02-01'到'2020-04-01'之间的时间范围内每个批准交易的时差,重复用户是在该时间范围结束之前进行交易,并且在该时间范围内至少再次进行了1次交易,在这种情况下,用户在“ 2020-04-01”之前进行了批准交易,而在“ 2020-04-01”之间用户至少又进行了1次批准交易2020-02-01”和“ 2020-04-01”。

针对该问题,我基于@Akina的答案使用了此查询

-- Get pairs (current transaction,prevIoUs transaction) for these users

SELECT t1.user_id,t1.createdAt,t2.createdAt,DATEDIFF(t2.createdAt,t1.createdAt) diff
-- table for a transaction
FROM test t1
-- table for prev. transaction
JOIN test t2 ON t1.user_id = t2.user_id 
            AND t1.createdAt < t2.createdAt
            AND 7 NOT IN (t1.status_id,t2.status_id)
-- get data only for users from prev. query
JOIN (SELECT t3.user_id
      FROM test t3
      WHERE t3.status_id != 7
      GROUP BY t3.user_id
      HAVING SUM(t3.createdAt < '2020-04-01') > 1
         AND SUM(t3.createdAt BETWEEN '2020-02-01' AND '2020-04-01')) t4 ON t1.user_id = t4.user_id
-- check that there is no approved transaction between selected transactions
WHERE NOT EXISTS (SELECT NULL
                   FROM test t5
                   WHERE t1.user_id = t5.user_id
                     AND t5.status_id != 7
                     AND t1.createdAt < t5.createdAt
                     AND t5.createdAt < t2.createdAt)

the output table was like this 
+----------+------------+------------+------+
|  user_id | createdAt  | createdAt  | diff |
+----------+------------+------------+------+
|       13 | 2020-01-01 | 2020-01-03 |    2 |
|       13 | 2020-01-03 | 2020-01-06 |    3 |
|       14 | 2020-03-02 | 2020-03-03 |    1 |
|       13 | 2020-01-06 | 2020-03-04 |   58 |
|       14 | 2020-03-03 | 2020-03-10 |    7 |
+----------+------------+------------+------+

问题是,此查询对每个用户的时间范围(“ 2020-02-01”至“ 2020-04-01”)中的时间差进行计数,并对时间范围之前的时间差进行计数(请参阅users_id 13,用户还计算了日期“ 2020-01-01”到“ 2020-01-03”之间的时差)。我想要的是,如果用户在时间范围之前进行了交易,则我只希望计算他在时间范围之前的users_id最后一次交易(在这种情况下,我要仅计算“ 2020-01-06”中的时差的users_id 13)直到'2020-03-04',因为2020年1月6日是用户在时间范围之前的最后一次交易的日期。在这种情况下,预期结果是这样的:

+---------+------------+------------+------+
| user_id | createdAt  | createdAt  | diff |
+---------+------------+------------+------+
|      14 | 2020-03-02 | 2020-03-03 |    1 |
|      13 | 2020-01-06 | 2020-03-04 |   58 |
|      14 | 2020-03-03 | 2020-03-10 |    7 |
+---------+------------+------------+------+

解决方法

我认为您只需要排除在时间范围BETWEEN '2020-02-01' AND '2020-04-01之前结束的所有事务,因为它们不感兴趣。 由于您已经排除了超出时间范围的所有内容

您仍然知道在事务开始和结束时输入数据的时间,因此您应该在一个额外的列中标记在一起的行,这除了使您无法使用的状态之外,还可以使查询更加简单,因为它会重复

SELECT t1.user_id,t1.createdAt,t2.createdAt createcompare,DATEDIFF(t2.createdAt,t1.createdAt) diff
-- table for a transaction
FROM test t1
-- table for prev. transaction
JOIN test t2 ON t1.user_id = t2.user_id 
            AND t1.createdAt < t2.createdAt
            AND 7 NOT IN (t1.status_id,t2.status_id)
JOIN (SELECT t3.user_id
      FROM test t3
      WHERE t3.status_id != 7
      GROUP BY t3.user_id
      HAVING SUM(t3.createdAt < '2020-04-01') > 1
         AND SUM(t3.createdAt BETWEEN '2020-02-01' AND '2020-04-01')) t4 ON t1.user_id = t4.user_id
WHERE NOT EXISTS (SELECT NULL
                   FROM test t5
                   WHERE t1.user_id = t5.user_id
                     AND t5.status_id != 7
                     AND t1.createdAt < t5.createdAt
                     AND t5.createdAt < t2.createdAt) 
HAViNG createcompare > '2020-02-01'
user_id | createdAt  | cretecompare | diff
------: | :--------- | :----------- | ---:
     14 | 2020-03-02 | 2020-03-03   |    1
     13 | 2020-01-06 | 2020-03-04   |   58
     14 | 2020-03-03 | 2020-03-10   |    7
     13 | 2020-03-04 | 2020-04-10   |   37

db 提琴https://github.com/lipoyang/Arduino_de_EtherCAT/blob/master/ec_slave1/ec_slave1.ino

更新:

这实际上更有意义

SELECT t1.user_id,t1.createdAt cretecompare1,t2.createdAt cretecompare2,t2.status_id)
JOIN (SELECT t3.user_id
      FROM test t3
      WHERE t3.status_id != 7
      GROUP BY t3.user_id
      HAVING SUM(t3.createdAt < '2020-04-01') > 1
         AND SUM(t3.createdAt BETWEEN '2020-02-01' AND '2020-04-01')) t4 ON t1.user_id = t4.user_id
WHERE NOT EXISTS (SELECT NULL
                   FROM test t5
                   WHERE t1.user_id = t5.user_id
                     AND t5.status_id != 7
                     AND t1.createdAt < t5.createdAt
                     AND t5.createdAt < t2.createdAt) 
HAViNG cretecompare2  BETWEEN '2020-02-01' AND '2020-04-01'
user_id | cretecompare1 | cretecompare2 | diff
------: | :------------ | :------------ | ---:
     14 | 2020-03-02    | 2020-03-03    |    1
     13 | 2020-01-06    | 2020-03-04    |   58
     14 | 2020-03-03    | 2020-03-10    |    7

db 提琴here