如何使用 mysql 找出每个用户每笔交易的时差(当天)
how to find out time difference (on day) for every transaction on each users using mysql
我有一个 table 这样的:
CREATE TABLE test (
ID SERIAL PRIMARY KEY,
user_id INT,
createdAt DATE,
status_id INT
);
INSERT INTO test VALUES
(1, 12, '2020-01-01', 4),
(2, 12, '2020-01-03', 7),
(3, 12, '2020-01-06', 7),
(4, 13, '2020-01-02', 5),
(5, 13, '2020-01-03', 6),
(6, 14, '2020-03-03', 8),
(7, 13, '2020-03-04', 4),
(8, 15, '2020-04-04', 7),
(9, 14, '2020-03-02', 6),
(10, 14, '2020-03-10', 5),
(11, 13, '2020-04-10', 8);
其中 table 每笔交易的 ID 有 id
,user_id
是用户,createdAt
是交易发生的日期,status_id
是每笔交易的状态(在这种情况下 status_id
4、5、6、8 是已批准的交易)
我想找出在“2020-02-01”和“2020-04-01”之间进行交易并批准了超过 1 笔交易的每个用户的每笔交易的最大、最小、平均不同日期时期
这是我的查询:
SELECT MIN(diff) AS `MIN`, MAX(diff) AS `MAX`, SUM(diff) / COUNT(DISTINCT user_id) AS `AVG`
FROM (
SELECT ID, user_id, DATEDIFF((SELECT t2.createdAt FROM test t2 WHERE t2.user_id = t1.user_id AND t1.createdAt <= t2.createdAt AND t2.id <> t1.id LIMIT 1), t1.createdAt) AS diff
FROM test t1
where
status_id in (4, 5, 6, 8)
HAVING SUM(t1.user_id BETWEEN '2020-02-01' AND '2020-04-01')
AND SUM(t1.user_id >= '2020-02-01') > 1
) DiffTable
WHERE diff IS NOT NULL
但是据说:
In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'fiddle_KDQIQDMUZEIOVXFHRZPY.t1.ID'; this is incompatible with sql_mode=only_full_group_by
我该怎么办?
预期结果
+-----+-----+---------+
| MAX | MIN | AVERAGE |
+-----+-----+---------+
| 36 | 1 | 22 |
+-----+-----+---------+
解释:
- the user_id who have approval transaction on 2020-02-01 until 2020-04-01 and user_id who have transaction more than 1 are user_id 13 & 14
- the maximum of different day on 2020-02-01 until 2020-04-01 are user_id 13 which the different day for each transaction happen in 2020-03-04 and doing next transaction again in 2020-04-10
- the minimum day of different day of each transaction are user_id 14 who doing transaction on 2020-03-02 and next transaction 2020-03-03
- average are 22 days (sum of different day on user_Id 13 & 14 / amount of user_id who fit on this condition)
您需要在子查询之外执行 GROUP
ing;子查询应该只用于将 selected 事务限制为具有所需 status_id
值和所需范围内的日期的事务。那么就可以在外层查询select个时间段内有一笔以上交易的用户:
SELECT user_id,
COUNT(*) AS transactions,
MIN(diff) AS `MIN`,
MAX(diff) AS `MAX`,
SUM(diff) / COUNT(diff) AS `AVG`
FROM (
SELECT user_id, DATEDIFF((SELECT MIN(t2.createdAt)
FROM test t2
WHERE t2.user_id = t1.user_id
AND t1.createdAt < t2.createdAt
AND t2.status_id in (4, 5, 6, 8)
), t1.createdAt) AS diff
FROM test t1
WHERE status_id in (4, 5, 6, 8)
AND createdAt BETWEEN '2020-02-01' AND '2020-04-01'
) DiffTable
WHERE diff IS NOT NULL
GROUP BY user_id
HAVING COUNT(*) > 1
输出(对于你的fiddle):
user_id transactions MIN MAX AVG
14 2 1 7 4.0000
如果您想要基于该期间发生的 所有 笔交易的值,而不是 user_id
,您可以简单地删除 GROUP BY
和HAVING
个子句:
SELECT COUNT(*) AS transactions,
MIN(diff) AS `MIN`,
MAX(diff) AS `MAX`,
SUM(diff) / COUNT(diff) AS `AVG`
FROM (
SELECT user_id, DATEDIFF((SELECT MIN(t2.createdAt)
FROM test t2
WHERE t2.user_id = t1.user_id
AND t1.createdAt < t2.createdAt
AND t2.status_id in (4, 5, 6, 8)
), t1.createdAt) AS diff
FROM test t1
WHERE status_id in (4, 5, 6, 8)
AND createdAt BETWEEN '2020-02-01' AND '2020-04-01'
) DiffTable
WHERE diff IS NOT NULL
输出:
transactions MIN MAX AVG
3 1 37 15.0000
请注意,DATEDIFF
计算中的现有子查询存在一些问题:没有 ORDER BY
的 LIMIT
不能保证给出预期的结果,并且没有以 status_id
为条件。我已在更新的查询中修复了这两个问题。
我有一个 table 这样的:
CREATE TABLE test (
ID SERIAL PRIMARY KEY,
user_id INT,
createdAt DATE,
status_id INT
);
INSERT INTO test VALUES
(1, 12, '2020-01-01', 4),
(2, 12, '2020-01-03', 7),
(3, 12, '2020-01-06', 7),
(4, 13, '2020-01-02', 5),
(5, 13, '2020-01-03', 6),
(6, 14, '2020-03-03', 8),
(7, 13, '2020-03-04', 4),
(8, 15, '2020-04-04', 7),
(9, 14, '2020-03-02', 6),
(10, 14, '2020-03-10', 5),
(11, 13, '2020-04-10', 8);
其中 table 每笔交易的 ID 有 id
,user_id
是用户,createdAt
是交易发生的日期,status_id
是每笔交易的状态(在这种情况下 status_id
4、5、6、8 是已批准的交易)
我想找出在“2020-02-01”和“2020-04-01”之间进行交易并批准了超过 1 笔交易的每个用户的每笔交易的最大、最小、平均不同日期时期
这是我的查询:
SELECT MIN(diff) AS `MIN`, MAX(diff) AS `MAX`, SUM(diff) / COUNT(DISTINCT user_id) AS `AVG`
FROM (
SELECT ID, user_id, DATEDIFF((SELECT t2.createdAt FROM test t2 WHERE t2.user_id = t1.user_id AND t1.createdAt <= t2.createdAt AND t2.id <> t1.id LIMIT 1), t1.createdAt) AS diff
FROM test t1
where
status_id in (4, 5, 6, 8)
HAVING SUM(t1.user_id BETWEEN '2020-02-01' AND '2020-04-01')
AND SUM(t1.user_id >= '2020-02-01') > 1
) DiffTable
WHERE diff IS NOT NULL
但是据说:
In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'fiddle_KDQIQDMUZEIOVXFHRZPY.t1.ID'; this is incompatible with sql_mode=only_full_group_by
我该怎么办?
预期结果
+-----+-----+---------+
| MAX | MIN | AVERAGE |
+-----+-----+---------+
| 36 | 1 | 22 |
+-----+-----+---------+
解释:
- the user_id who have approval transaction on 2020-02-01 until 2020-04-01 and user_id who have transaction more than 1 are user_id 13 & 14
- the maximum of different day on 2020-02-01 until 2020-04-01 are user_id 13 which the different day for each transaction happen in 2020-03-04 and doing next transaction again in 2020-04-10
- the minimum day of different day of each transaction are user_id 14 who doing transaction on 2020-03-02 and next transaction 2020-03-03
- average are 22 days (sum of different day on user_Id 13 & 14 / amount of user_id who fit on this condition)
您需要在子查询之外执行 GROUP
ing;子查询应该只用于将 selected 事务限制为具有所需 status_id
值和所需范围内的日期的事务。那么就可以在外层查询select个时间段内有一笔以上交易的用户:
SELECT user_id,
COUNT(*) AS transactions,
MIN(diff) AS `MIN`,
MAX(diff) AS `MAX`,
SUM(diff) / COUNT(diff) AS `AVG`
FROM (
SELECT user_id, DATEDIFF((SELECT MIN(t2.createdAt)
FROM test t2
WHERE t2.user_id = t1.user_id
AND t1.createdAt < t2.createdAt
AND t2.status_id in (4, 5, 6, 8)
), t1.createdAt) AS diff
FROM test t1
WHERE status_id in (4, 5, 6, 8)
AND createdAt BETWEEN '2020-02-01' AND '2020-04-01'
) DiffTable
WHERE diff IS NOT NULL
GROUP BY user_id
HAVING COUNT(*) > 1
输出(对于你的fiddle):
user_id transactions MIN MAX AVG
14 2 1 7 4.0000
如果您想要基于该期间发生的 所有 笔交易的值,而不是 user_id
,您可以简单地删除 GROUP BY
和HAVING
个子句:
SELECT COUNT(*) AS transactions,
MIN(diff) AS `MIN`,
MAX(diff) AS `MAX`,
SUM(diff) / COUNT(diff) AS `AVG`
FROM (
SELECT user_id, DATEDIFF((SELECT MIN(t2.createdAt)
FROM test t2
WHERE t2.user_id = t1.user_id
AND t1.createdAt < t2.createdAt
AND t2.status_id in (4, 5, 6, 8)
), t1.createdAt) AS diff
FROM test t1
WHERE status_id in (4, 5, 6, 8)
AND createdAt BETWEEN '2020-02-01' AND '2020-04-01'
) DiffTable
WHERE diff IS NOT NULL
输出:
transactions MIN MAX AVG
3 1 37 15.0000
请注意,DATEDIFF
计算中的现有子查询存在一些问题:没有 ORDER BY
的 LIMIT
不能保证给出预期的结果,并且没有以 status_id
为条件。我已在更新的查询中修复了这两个问题。