如何在 MySQL 中每天创建一个自增 ID?
How can I create a self-incrementing ID per day in MySQL?
我有一个table
bills
( id INT NOT NULL AUTOINCREMENT PRIMARY KEY
, createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
, idDay INT NULL
);
我希望每一天的idDay字段的第一条记录为1,并从那里继续递增,示例:
| id | createdAt | idDay |
|----------|----------------|-------|
| 1 | 2021-01-10 | 1 |
| 2 | 2021-01-10 | 2 |
| 3 | 2021-01-11 | 1 |
| 4 | 2021-01-11 | 2 |
| 5 | 2021-01-11 | 3 |
| 6 | 2021-01-12 | 1 |
| 7 | 2021-01-13 | 1 |
| 8 | 2021-01-13 | 2 |
idDay 字段是必须的吗?或者我可以在 select 中执行此操作吗?
我想我可以通过程序来做到这一点,但是怎么做呢?
感谢您的帮助。
您可以使用 row_number()
window 功能自 MySQL 8.
SELECT id,
createdat,
row_number() OVER (PARTITION BY date(createdat)
ORDER BY id) idday
FROM bill;
(或 ORDER BY createdat
,如果定义顺序,则不是 id
。)
但由于 window 函数是在应用 WHERE
子句后计算的,如果过滤了一天的先前记录,记录的数字可能会有所不同。从你的问题中不清楚这是否是一个问题。如果这是一个问题,您可以在派生的 table 中使用查询或使用它创建一个视图并进行处理。
另一个选项是计算“较旧”记录的相关子查询。
SELECT b1.id,
b1.createdat,
(SELECT count(*) + 1
FROM bill b2
WHERE b2.createdat >= date(b1.cratedat)
AND b2.createdat < date_add(date(b1.createdat), INTERVAL 1 DAY))
AND b2.id < b1.id) idday
FROM bill b1;
(如果createdat
定义了顺序,将b2.createdat < date_add(date(b1.createdat), INTERVAL 1 DAY))
改为b2.createdat <= b1.createdat
。)
这也适用于较低的 MySQL 版本,您可以在不更改数字的情况下添加 WHERE
子句(到外部查询)。
您可以只计算 select 中的数字(需要 createdAt 上的索引才能正常工作):
select b.id, b.createdAt, count(b2.id)+1 as idDay
from bill b
left join bill b2 on b2.createdAt=b.createdAt and b2.id < b.id
where ...
group by b.id
我有一个table
bills
( id INT NOT NULL AUTOINCREMENT PRIMARY KEY
, createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
, idDay INT NULL
);
我希望每一天的idDay字段的第一条记录为1,并从那里继续递增,示例:
| id | createdAt | idDay |
|----------|----------------|-------|
| 1 | 2021-01-10 | 1 |
| 2 | 2021-01-10 | 2 |
| 3 | 2021-01-11 | 1 |
| 4 | 2021-01-11 | 2 |
| 5 | 2021-01-11 | 3 |
| 6 | 2021-01-12 | 1 |
| 7 | 2021-01-13 | 1 |
| 8 | 2021-01-13 | 2 |
idDay 字段是必须的吗?或者我可以在 select 中执行此操作吗? 我想我可以通过程序来做到这一点,但是怎么做呢?
感谢您的帮助。
您可以使用 row_number()
window 功能自 MySQL 8.
SELECT id,
createdat,
row_number() OVER (PARTITION BY date(createdat)
ORDER BY id) idday
FROM bill;
(或 ORDER BY createdat
,如果定义顺序,则不是 id
。)
但由于 window 函数是在应用 WHERE
子句后计算的,如果过滤了一天的先前记录,记录的数字可能会有所不同。从你的问题中不清楚这是否是一个问题。如果这是一个问题,您可以在派生的 table 中使用查询或使用它创建一个视图并进行处理。
另一个选项是计算“较旧”记录的相关子查询。
SELECT b1.id,
b1.createdat,
(SELECT count(*) + 1
FROM bill b2
WHERE b2.createdat >= date(b1.cratedat)
AND b2.createdat < date_add(date(b1.createdat), INTERVAL 1 DAY))
AND b2.id < b1.id) idday
FROM bill b1;
(如果createdat
定义了顺序,将b2.createdat < date_add(date(b1.createdat), INTERVAL 1 DAY))
改为b2.createdat <= b1.createdat
。)
这也适用于较低的 MySQL 版本,您可以在不更改数字的情况下添加 WHERE
子句(到外部查询)。
您可以只计算 select 中的数字(需要 createdAt 上的索引才能正常工作):
select b.id, b.createdAt, count(b2.id)+1 as idDay
from bill b
left join bill b2 on b2.createdAt=b.createdAt and b2.id < b.id
where ...
group by b.id