下面分享使用三种方法计算用户最近两次交易时间差。
01 数据准备
假设有一张表transactions,一列是用户id(user_id),一列是交易时间(transaction_time),问用户最近一次交易时间和倒数第二次交易时间之差,单位:秒。
示例表数据如下,具体建表及插入数据语句见文末附录:
02 解题思路及SQL答案
解题思路一:使用窗口函数 — row_number() over()函数
在公共表达式中使用窗口函数ROW_NUMBER()为每个用户的交易时间降序排列;
使用自连接,将每个用户的每次交易时间与其倒数第二次交易时间关联;
筛选最近一次交易时间的记录并计算最近一次交易时间与倒数第二次交易时间相差秒数。
SQL如下:
WITH RankedTransactions AS (
SELECT
user_id,
transaction_time,
ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY transaction_time DESC) AS rn
FROM
transactions
)
SELECT
t1.user_id,
t1.transaction_time as latest_time,
t2.transaction_time as second_latest_time,
TIMESTAMPDIFF(SECOND, t2.transaction_time, t1.transaction_time) AS time_difference_s
FROM
RankedTransactions t1
JOIN
RankedTransactions t2 ON t1.user_id = t2.user_id AND t2.rn = 2
WHERE
t1.rn = 1;
结果如下:
解题思路二:使用公共表达式与表连接
SQL如下:
-- 第一步:找出每个用户的最近一次交易时间
WITH LatestTransactions AS (
SELECT
user_id,
MAX(transaction_time) AS latest_time
FROM
transactions
GROUP BY
user_id
),
-- 第二步:剔除最近一次交易时间后,找出每个用户的最近一次交易时间(即倒数第二次)
SecondLatestTransactions AS (
SELECT
t.user_id,
MAX(t.transaction_time) AS second_latest_time
FROM
transactions t
LEFT JOIN
LatestTransactions lt ON t.user_id = lt.user_id
AND t.transaction_time = lt.latest_time
WHERE
lt.latest_time IS NULL OR t.transaction_time < lt.latest_time
GROUP BY
t.user_id
)
-- 第三步:将两个子查询结果关联起来,并计算时间差
SELECT
lt.user_id,
latest_time,
second_latest_time,
TIMESTAMPDIFF(SECOND, slt.second_latest_time, lt.latest_time) AS time_difference
FROM
LatestTransactions lt
JOIN
SecondLatestTransactions slt ON lt.user_id = slt.user_id;
结果如下:
解题思路三:窗口函数、子查询结合法
第一步:对每个用户的交易时间降序并位移获取下一个交易时间,这时候最近一次交易时间和倒数第二次交易时间就在每一个用户id的第一行;
第二步:计算每个用户的交易时间和其降序排列的下一个交易时间之差,并使用窗口函数对每个用户的交易时间降序排列;
第三步:筛选最近一次交易时间,即可得到计算后的结果。
SQL如下:
-- 第三步:筛选最近一次交易时间,即可得到计算后的结果
SELECT
user_id,
transaction_time,
next_time,
time_difference
FROM
(
-- 第二步:计算每个用户的交易时间和其降序排列的下一个交易时间之差,并使用窗口函数对每个用户的交易时间降序排列
SELECT
user_id,
transaction_time,
next_time,
TIMESTAMPDIFF(SECOND, next_time, transaction_time) AS time_difference,
ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY transaction_time DESC) AS rn
FROM
-- 第一步:对每个用户的交易时间降序并位移获取下一个交易时间,这时候最近一次交易时间和倒数第二次交易时间就在每一个用户id的第一行
(
SELECT
user_id,
transaction_time,
LEAD(transaction_time) OVER (PARTITION BY user_id ORDER BY transaction_time DESC) AS next_time
FROM
transactions
)a
)a
WHERE rn = 1
;
结果如下:
附录
建表及插入数据语句:
CREATE TABLE transactions (
user_id INT,
transaction_time datetime
);
insert into transactions values
('123', '2024-01-01 15:30:30'),
('123', '2024-01-02 16:50:00'),
('123', '2024-01-03 16:51:38'),
('123', '2024-01-04 15:30:30'),
('234', '2024-01-01 16:51:38'),
('234', '2024-01-04 12:35:00'),
('234', '2024-01-07 09:58:00'),
('345', '2024-01-01 16:51:38'),
('345', '2024-01-02 15:30:30'),
('345', '2024-03-16 16:51:38'),
('345', '2024-03-17 12:35:00'),
('345', '2024-03-18 16:51:38'),
('456', '2024-03-04 16:51:38'),
('456', '2024-03-08 09:58:00'),
('456', '2024-03-09 12:35:00'),
('456', '2024-03-13 15:30:30');
以上就是本次的分享,感谢观看!
该文章在 2024/4/19 16:13:42 编辑过