问题描述
我有一张桌子
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 字段是必需的吗?或者我可以在选择中这样做吗? 我想我可以用一个程序来做到这一点,但怎么做?。
感谢您的帮助。 ?
解决方法
您可以使用自 MySQL 8 起可用的 row_number()
窗口函数。
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 < date_add(date(b1.createdat),INTERVAL 1 DAY))
更改为 b2.createdat <= b1.createdat
。)
这也适用于较低的 MySQL 版本,您可以在不更改数字的情况下添加 WHERE
子句(到外部查询)。
您可以只计算选择中的数字(需要在 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