MYSQL 插入缺少日期的行

MYSQL inserting rows with missing dates

我有一个包含两列的 table:

名字 日期
AA 2021-06-01
BB 2021-06-02
CC 2021-05-28

我想编写一个代码来添加具有名称和日期的行,直到今天 (2021-06-03) 日期,如下所示:

名字 日期
AA 2021-06-01
AA 2021-06-02
AA 2021-06-03
BB 2021-06-02
BB 2021-06-03
CC 2021-05-28
CC 2021-05-29
CC 2021-05-30
CC 2021-05-31
CC 2021-06-01
CC 2021-06-02
CC 2021-06-03

我没有使用过递归函数,所以不确定这里最好的做法是什么。任何正确方向的帮助或指示将不胜感激。谢谢:)

对于 MySQL 的最新版本,您可以...

DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(name CHAR(2) NOT NULL
,date DATE NOT NULL
,PRIMARY KEY(name,date)
);

INSERT INTO my_table VALUES
('AA','2021-06-01'),
('BB','2021-06-02'),
('CC','2021-05-28');

WITH RECURSIVE cte AS
(
  SELECT MIN(date) date FROM my_table 
   UNION ALL
  SELECT date + INTERVAL 1 DAY 
    FROM cte
   WHERE date + INTERVAL 1 DAY <= '2021-06-03'
)
SELECT x.name
     , cte.date
  FROM my_table x
  JOIN cte
    ON cte.date >= x.date
 ORDER 
    BY name
     , date


| name | date       |
| ---- | ---------- |
| AA   | 2021-06-01 |
| AA   | 2021-06-02 |
| AA   | 2021-06-03 |
| BB   | 2021-06-02 |
| BB   | 2021-06-03 |
| CC   | 2021-05-28 |
| CC   | 2021-05-29 |
| CC   | 2021-05-30 |
| CC   | 2021-05-31 |
| CC   | 2021-06-01 |
| CC   | 2021-06-02 |
| CC   | 2021-06-03 |

---

[View on DB Fiddle](https://www.db-fiddle.com/f/wL3ZqXoTqdKftJCPA4um4j/1)     

对于旧版本,您可以使用实用程序 table。例如,我有一个 table 的整数 (i),其值从 0 到 9...

SELECT y.name
     , x.date 
  FROM 
     ( SELECT MIN(date) + INTERVAL i DAY date FROM my_table,ints GROUP BY i HAVING date <= '2021-06-03' ) x 
  JOIN my_table y 
    ON y.date <= x.date 
 ORDER 
    BY name
     , date;
+------+------------+
| name | date       |
+------+------------+
| AA   | 2021-06-01 |
| AA   | 2021-06-02 |
| AA   | 2021-06-03 |
| BB   | 2021-06-02 |
| BB   | 2021-06-03 |
| CC   | 2021-05-28 |
| CC   | 2021-05-29 |
| CC   | 2021-05-30 |
| CC   | 2021-05-31 |
| CC   | 2021-06-01 |
| CC   | 2021-06-02 |
| CC   | 2021-06-03 |
+------+------------+

您想从 table 中的行到日期 '2021-06-03' 生成行。您可以直接使用递归 CTE 执行此操作:

with recursive cte as (
      select name, date
      from t
      union all
      select name, date + interval 1 day
      from cte
      where date < '2021-06-03'
     )
select *
from cte
order by name, date;

Here 是一个 db<>fiddle.

您可以将递归 CTE 解读为:

  • 从给定 table 中的行开始。
  • 在日期上加一天。
  • 当日期为结束日期时停止。

这不仅比“生成所有日期”然后加入更简单,而且应该更快。