如何在MySQL中每天创建一个自增ID?

如何在MySQL中每天创建一个自增ID?,mysql,sql,auto-increment,Mysql,Sql,Auto Increment,我有一张桌子 bills ( id INT NOT NULL AUTOINCREMENT PRIMARY KEY , createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , idDay INT NULL ); 我希望每天idDay字段的第一条记录为1,然后继续递增,例如: | id | createdAt | idDay | |----------|----------------|-------| | 1

我有一张桌子

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?中执行此操作?。 我想我可以通过一个程序做到这一点,但如何做到

谢谢你的帮助 您可以使用MySQL 8提供的行数窗口功能

SELECT id,
       createdat,
       row_number() OVER (PARTITION BY date(createdat)
                          ORDER BY id) idday
       FROM bill;
或ORDER BY createdat,如果它定义的是顺序,而不是id

但是,由于窗口函数是在应用WHERE子句之后计算的,因此如果过滤了一天以前的记录,则记录的数字可能会不同。你的问题不清楚这是否是个问题。如果有问题,您可以在派生表中使用该查询,或者使用该查询创建一个视图并进行处理

还有一个选项是计算旧记录的相关子查询

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
SELECT id,
       createdat,
       row_number() OVER (PARTITION BY date(createdat)
                          ORDER BY id) idday
       FROM bill;
或ORDER BY createdat,如果它定义的是顺序,而不是id

但是,由于窗口函数是在应用WHERE子句之后计算的,因此如果过滤了一天以前的记录,则记录的数字可能会不同。你的问题不清楚这是否是个问题。如果有问题,您可以在派生表中使用该查询,或者使用该查询创建一个视图并进行处理

还有一个选项是计算旧记录的相关子查询

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
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

您只需计算select中的数字即可。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

为什么不将日期散列?您会问这样一个问题:是否需要idDay字段你是能够回答这个问题的人,我认为这是第一个需要回答的问题。你认为你在这个领域取得了什么成就?你希望/期望使用该字段做什么,而仅仅使用id和createdAt字段是无法实现的?@Craig,你是对的,我的意思是,如果我只使用select,这对我来说是不必要的。在这种情况下,@sticky bit的答案会让你达到目的,通过在SELECT语句中生成每个日期的自动增量为什么不散列日期的可能重复?您会问这样一个问题:是否需要idDay字段你是能够回答这个问题的人,我认为这是第一个需要回答的问题。你认为你在这个领域取得了什么成就?你希望/期望使用该字段做什么,而仅仅使用id和createdAt字段是无法实现的?@Craig,你是对的,我的意思是,如果我只使用select,这对我来说是不必要的。在这种情况下,@sticky bit的答案会让你达到目的,通过在SELECT语句中生成每个日期的自动增量,仅当您希望获取的每个记录还需要该天以前的所有记录时,该语句才可能重复。否则,您将需要一个子查询,此时您最好使用selfjoin@ysth:公平点。我编辑了答案来解决这个问题。只有当你想要得到的每一条记录,你也想要那一天以前的所有记录时,这才有效。否则,您将需要一个子查询,此时您最好使用selfjoin@ysth:公平点。我编辑了答案以解决这个问题。