【问题标题】:Postgres - create a column (alter table) as a calculation of other two columnsPostgres - 创建一个列(更改表)作为其他两列的计算
【发布时间】:2021-01-17 21:03:42
【问题描述】:

我在 Posgres 中有一个表,其中包含任务开始日期和任务结束日期。可以在此故事中生成一列,作为(当前日期 - 开始日期)/(开始日期 - 结束日期)之间的比率,该列是经过的时间百分比。我用这种方法试了,还是不行。

ALTER TABLE public.gantt_task
ADD COLUMN 
      percentage_progress 
GENERATED  ALWAYS AS (
(DATEDIFF("day", 
CURRENT_DATE,public.gantt_Tasks.start_date)) / DATEDIFF("day", public.gantt_Tasks.end_date ,public.gantt_Tasks.start_date)) 
STORED 

【问题讨论】:

  • 除非您创建了自己的版本,否则 Postgres 中没有 DATEDIFF。尝试类似:select current_date - '10/31/2020'::date; 78.

标签: postgresql autogeneratecolumn


【解决方案1】:

手册说 postgres 只支持物化(即存储)生成的列,这意味着该值是在插入或更新行时生成的,这意味着它将使用插入/更新日期,而不是您想要的 CURRENT_DATE。

因此,您需要创建一个视图。这允许在 SELECT 日期而不是 INSERT/UPDATE 日期评估 CURRENT_DATE 以生成列。

CREATE VIEW foo AS SELECT *, 
  (CURRENT_DATE - public.gantt_Tasks.start_date)
  / (public.gantt_Tasks.end_date-public.gantt_Tasks.start_date)
  AS percentage_progress
FROM public.gantt_task

注意 DATEDIFF 是 mysql 语法而不是 postgres,并且不允许除以零,因此如果 start_date 和 end_date 可以相同,那么您必须根据需要修改表达式条件。此外,当 CURRENT_DATE 晚于 end_date 时,您的表达将超过 100%。可能是这样的:

least( 1.0, (CURRENT_DATE-start_date)/greatest( 1, end_date-start_date)::FLOAT )

【讨论】:

  • 另一种选择是创建一个包含该表达式的不可变函数,以“欺骗”Postgres 允许它用于生成的列。但是视图也行不通。 Postgres中没有datediff()函数
  • 如果函数包含 CURRENT_DATE 那么 postgres 将不允许它被声明为不可变的。是的,DATEDIFF 是 MySQL 语法...
  • 你说得对,我把它和 STABLE 混在一起了。不会改变将使用插入日期而不是选择日期生成和存储列的事实...
【解决方案2】:

我不会编写正确的 SQL 代码。但是您可能/应该将其拆分为两个或三个任务:

  1. 添加允许 null 的新列(应该是默认值)
  2. 更新表格
  3. 添加约束(如果需要)

【讨论】:

    猜你喜欢
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 2021-10-22
    相关资源
    最近更新 更多