有一个订单表 t_order,有关 t_order 的描述见下表。
字段 | 类型 | 描述 |
---|---|---|
id | Integer | 主键 |
create_ts | Datetime | 创建时间 |
uid | Integer | 用户ID |
is_suc | Integer | 订单状态 1-成功 0-失败 |
t_order 的数据如下:
id create_ts uid is_suc
------ ------------------- ------ --------
1 2020-01-01 11:21:24 1 1
2 2020-01-02 20:41:10 1 0
3 2020-01-03 8:12:14 1 0
4 2020-01-04 22:50:24 2 1
5 2020-01-05 6:39:45 1 0
6 2020-01-06 19:10:51 2 0
7 2020-01-07 14:12:40 1 1
8 2020-01-08 17:12:10 2 1
9 2020-01-09 23:22:52 1 0
10 2020-01-10 5:10:28 2 0
现在要做的是在 t_order 表中增加一列 last_id,用于展示上一个状态为“成功”的订单的 id,若找不到符合条件的订单,则 last_id 为 NULL
。
最终要实现的结果如下:
id create_ts uid is_suc last_id
------ ------------------- ------ ------ ---------
1 2020-01-01 11:21:24 1 1 (NULL)
2 2020-01-02 20:41:10 1 0 1
3 2020-01-03 8:12:14 1 0 1
4 2020-01-04 22:50:24 2 1 (NULL)
5 2020-01-05 6:39:45 1 0 1
6 2020-01-06 19:10:51 2 0 4
7 2020-01-07 14:12:40 1 1 1
8 2020-01-08 17:12:10 2 1 4
9 2020-01-09 23:22:52 1 0 7
10 2020-01-10 5:10:28 2 0 8
需要明确的是,相对于当前订单的“上一个订单”是依据创建时间来选择,而不是主键。
暂时假设 t_order 中每个用户的订单的创建时间对应着主键单调递增,那我们就可以说最靠近当前订单的创建时间的记录就是要锁定的上一个订单。
要得到当前订单的上一个状态为“成功”的订单,可使用下面的 SQL 获取:
SELECT
MAX(id)
FROM
t_order
WHERE is_suc = 1
AND uid = 当前订单的所属用户
AND create_ts < 当前订单的创建时间
完整的 SQL 如下:
SELECT
*,
(SELECT
MAX(id)
FROM
t_order
WHERE is_suc = 1
AND uid = a.uid
AND create_ts < a.create_ts ) AS last_id
FROM
t_order a
我们前面做了一个假设,假设每个用户的订单的创建时间是随着主键递增的,但有时候并不是这样。有的订单的创建得比较早,但是进入到数据库比较晚,因此就会出现在两条订单记录中,ID 较小的记录的创建时间比 ID 大的记录的创建时间还要晚的情况。如果是这种情况,就不能应用上面的 SQL 。
可以先筛选出小于当前订单的创建时间的所有记录,重新排序后只取创建时间最大的那条记录。
用 SQL 来表示:
SELECT
id
FROM
t_order
WHERE is_suc = 1
AND uid = 当前订单的所属用户
AND create_ts < 当前订单的创建时间
ORDER BY create_ts DESC
LIMIT 1
完整的 SQL:
SELECT
*,
(SELECT
id
FROM
t_order
WHERE is_suc = 1
AND uid = a.uid
AND create_ts < a.create_ts
ORDER BY create_ts DESC
LIMIT 1) AS last_id
FROM
t_order a