PostgreSQL 按天分组时间戳

PostgreSQL grouping timestamp by day

我有一个 table x(x_id, ts),其中 ts 是时间戳。 我还有第二个 table y(y_id, day, month, year),它的值应该来自 x(ts)。 (x_id和y_id都是连续的) 例如:

            x                                  y

_x_id_|__________ts__________        _y_id_|_day_|_month_|__year__
  1   | '2019-10-17 09:10:08'          1     17     10      2019
  2   | '2019-01-26 11:12:02'          2     26      1      2019

但是,如果在 x 上我有 2 个时间戳在同一天但时间不同,那么这两个 table 应该是这样的:

            x                                  y

_x_id_|__________ts__________        _y_id_|_day_|_month_|__year__
  1   | '2019-10-17 09:10:08'          1     17     10      2019
  2   | '2019-10-17 11:12:02'        

意思是 y 不能有 2 行具有同一年月日。 目前,我这样做的方式是:

INSERT INTO y(day, month, year)
SELECT
EXTRACT(day FROM ts) AS day,
EXTRACT(month FROM ts) AS month,
EXTRACT(year FROM ts) AS year
FROM x
ORDER BY year, month, day;

但是,您可能知道,这不会检查时间戳是否共享同一日期,那么我该怎么做呢? 感谢您的宝贵时间!

在 table y 上添加 UNIQUE 约束以 防止 添加相同的日期两次。

CREATE UNIQUE INDEX CONCURRENTLY y_date 
ON y (year,month,day)

然后添加到y:

ALTER TABLE y
ADD CONSTRAINT y_unique_date
UNIQUE USING INDEX y_date

请注意,如果违反约束,您将收到 SQL 错误。如果您不想那样做而忽略 INSERT,请使用 BEFORE INSERT trigger, returning NULL when you detect the "date" already exists, or just use ON CONFLICT DO NOTHING in your INSERT statement, as .

假设您按照上面的建议构建唯一索引,将您的插入更改为:

insert into y(day, month, year)
  select extract(day from ts) as day,
       , extract(month from ts) as month,
       , extract(year from ts) as year
    from x
    on conflict do nothing;

我希望你的 table X 不是很大,因为上面的插入(就像你原来的那样)将尝试在每次执行时为 X 中的每一行插入一行到 Y - NO WHERE 子句。