13

我使用 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

输入条件值的伪代码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 

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

4

2 回答 2

12

一次性操作可以用一个简单的来实现UPDATE

UPDATE tbl
SET    one_year_survival = (survival OR survival_days >= 365);

我建议不要在你的名字中使用驼峰式、空格和括号。虽然允许在双引号之间,但它通常会导致复杂化和混乱。考虑手册中关于标识符和关键字的章节。

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

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

以这种方式开始时您不需要冗余列。


评论的附加答案

为避免空更新:

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)
...

就个人而言,如果我有令人信服的理由,我只会添加这些多余的列。通常我不会。如果是关于性能:你知道表达式和部分索引的索引吗?

于 2012-08-29T19:10:13.247 回答
6

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

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

那么你实际上可以:

SELECT *, m.one_year_survival from mytable m;

它会“正常工作”。请注意以下问题:

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

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

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

于 2012-08-30T00:49:36.297 回答