【问题标题】:How to insert 365 rows and increment date by one day for each row如何插入 365 行并为每一行增加一天的日期
【发布时间】: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),
  ...

问题:

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

【问题讨论】:

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

标签: java sql postgresql


【解决方案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 解决方案,这就是我必须要做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
相关资源
最近更新 更多