如何插入 365 行并为每一行增加一天的日期

Posted

技术标签:

【中文标题】如何插入 365 行并为每一行增加一天的日期【英文标题】:How to insert 365 rows and increment date by one day for each row 【发布时间】:2021-05-10 07:58:07 【问题描述】:

我有一张表,其架构如下:

date | from_city | to_city | rate_per_mile 

我想为一对城市 (city1, city2, rate) 插入今天的汇率,并为从今天开始到接下来的 365 天的所有日期创建 365 行。

date                   | from_city | to_city | rate_per_mile 
-------------------------------------------------------------
DATE(NOW())            | city1     | city2   | 13.23
DATE(NOW()) + 1 day    | city1     | city2   | 13.23
DATE(NOW()) + 2 days   | city1     | city2   | 13.23
DATE(NOW()) + 3 days   | city1     | city2   | 13.23
...
DATE(NOW()) + 365 days | city1     | city2   | 13.23

(date, from_city, to_city)是表的主键,我每天都会更新表,所以如果键已经存在一行,就应该替换它。

进行这些插入/更新的最佳方法是什么?最坏的情况,因为我必须从 java 程序中执行此操作,我将不得不创建 365 行并进行大批量插入:

INSERT INTO my_table
VALUES 
  (DATE(NOW()), city1, city2, 13.23),
  (DATE(NOW() + INTERVAL '1' day), city1, city2, 13.23),
  (DATE(NOW() + INTERVAL '2' day), city1, city2, 13.23),
  ...

问题:

    最好的方法是什么? 在这种情况下,我是否可以避免这些插入并创建视图来返回每个城市对未来 365 天预计的最新可用日期?如何创建这样的视图?

【问题讨论】:

这些费率每天都不同吗?如果不是,我会质疑每天 1 行的设计,并且可能会使用范围之类的东西,即放置开始(如果需要,结束)日期。如果您想获取某一天的费率,则可以查询其开始日期最接近该天但仍早于该天或同一天的行。这样一来,所有日子都具有相同费率的示例只会导致 1 个条目。 @Thomas 好点,但不幸的是,它们每天都会有所不同。 也许城市对应该移动到父表中? city_pair 表中的每一行在rate 表中都有零、一或多行? 【参考方案1】:

您可以为此使用generate_series()

INSERT INTO my_table (date, from_city, to_city, rate_per_mile)
select g.dt::date, 'city1', 'city2', 13.12
from generate_series(current_date, current_date + 364, interval '1 day') as g(dt);

【讨论】:

@daltonfury42:你想要 365 天还是真的想要 1 年。他们是不一样的; 365 天在大约 75% 的时间里是正确的。如果您总是想要一整年,请使用 generate_series(current_date, current_date + interval '1 year' - interval '1 day', interval '1 day) as g(dt)【参考方案2】:

由于您必须从 Java 中执行此操作,因此创建一个循环并使用批处理以获得更好的性能。

LocalDate today = LocalDate.now();
String fromCity = "city1";
String toCity = "city2";
BigDecimal ratePerMile = new BigDecimal("13.23");

try (Connection con = DriverManager.getConnection("...")) 
    String sql = "INSERT INTO my_table ( date, from_city, to_city, rate_per_mile ) VALUES (?,?,?,?)";
    try (PreparedStatement stmt = con.prepareStatement(sql)) 
        for (int daysToAdd = 0; daysToAdd <= 365; daysToAdd++) 
            LocalDate date = today.plusDays(daysToAdd);
            stmt.setObject(1, date);
            stmt.setString(2, fromCity);
            stmt.setString(3, toCity);
            stmt.setBigDecimal(4, ratePerMile);
            stmt.addBatch();
        
        stmt.executeBatch();
    

如果 JDBC 驱动程序不喜欢 LocalDate,请改用此行:

stmt.setDate(1, java.sql.Date.valueOf(date));

【讨论】:

是的,如果没有纯 SQL/DB 解决方案,这就是我必须要做的。

以上是关于如何插入 365 行并为每一行增加一天的日期的主要内容,如果未能解决你的问题,请参考以下文章

创建 365 天的视图

如何使用 node-postgres 进行批量插入

我应该为每一行插入调用 BigQuery 还是应该插入一个批量?

java如何创建一个指定的日期对象?

C ++从文本文件中读取行并编辑

用SQL获取某个某年某个月份的最后一天的日期