PostgreSQL创建一个新列,其值以其他列为条件

Zhu*_*arb 8 postgresql insert-update conditional-statements

我使用PostgreSQL 9.1.2并且我有一个基本表,如下所示,我将条目的生存状态作为布尔值 (Survival)以及天数(Survival(Days)).

我手动添加了一个名为的新列1-yr Survival,现在我想为表中的每个条目填写此列的值,条件是该条目的值SurvivalSurvival (Days)列值.一旦完成,数据库表将如下所示:

Survival    Survival(Days)    1-yr Survival
----------  --------------    -------------
Dead            200                NO
Alive            -                 YES
Dead            1200               YES
Run Code Online (Sandbox Code Playgroud)

输入条件值的伪代码1-yr Survival将类似于:

ALTER TABLE mytable ADD COLUMN "1-yr Survival" text
for each row
if ("Survival" = Dead & "Survival(Days)" < 365) then Update "1-yr Survival" = NO
else Update "1-yr Survival" = YES
end 
Run Code Online (Sandbox Code Playgroud)

我相信这是一个基本的操作,但我没有找到postgresql语法来执行它.一些搜索结果返回"添加触发器",但我不确定这是我所需要的.我认为我的情况要简单得多.任何帮助/建议将不胜感激.

Erw*_*ter 8

一次性操作可以通过简单的方式实现UPDATE:

UPDATE tbl
SET    one_year_survival = (survival OR survival_days >= 365);
Run Code Online (Sandbox Code Playgroud)

我建议不要在你的名字中使用驼峰,空格和括号.虽然在双引号之间允许,但它经常导致并发症和混乱.请考虑手册中有关标识符和关键字的章节.

您是否知道可以将查询结果导出为CSV COPY
例:

COPY (SELECT *, (survival OR survival_days >= 365) AS one_year_survival FROM tbl)
TO '/path/to/file.csv';
Run Code Online (Sandbox Code Playgroud)

您不需要以这种方式开始使用冗余列.


评论的补充答案

为避免空更新:

UPDATE tbl
SET    "Dead after 1-yr" = (dead AND my_survival_col < 365)
      ,"Dead after 2-yrs" = (dead AND my_survival_col < 730)
....
WHERE  "Dead after 1-yr" IS DISTINCT FROM (dead AND my_survival_col < 365)
   OR  "Dead after 2-yrs" IS DISTINCT FROM (dead AND my_survival_col < 730)
...
Run Code Online (Sandbox Code Playgroud)

就个人而言,如果我有一个令人信服的理由,我只会添加这些冗余列.通常我不会.如果是关于性能:您是否了解表达式和部分索引的索引


Chr*_*ers 5

老实说,我认为最好不要在数据库中存储数据,这可以通过存储的数据快速轻松地计算出来.一个更好的选择是模拟一个计算字段(然而,下面提到的问题).在这种情况下,您可以将空间等更改为下划线以便于维护:

CREATE FUNCTION one_yr_survival(mytable)
RETURNS BOOL
IMMUTABLE
LANGUAGE SQL AS $$
select $1.survival OR $1.survival_days >= 365;
$$;
Run Code Online (Sandbox Code Playgroud)

那么你实际上可以:

SELECT *, m.one_year_survival from mytable m;
Run Code Online (Sandbox Code Playgroud)

它会"正常工作".请注意以下问题:

  • mytable.1_year_survival不会被默认列列表返回,并且
  • 你不能省略表标识符(上例中的m),因为解析器将其转换为one_year_survival(m).

然而,好处是可以证明该值永远不会与其他值不同步.否则你最终会得到一个检查约束的老鼠窝.

实际上你可以采用这种方法.见http://ledgersmbdev.blogspot.com/2012/08/postgresql-or-modelling-part-2-intro-to.html