14

我想在我的表中创建一个(或两个)新字段,它是其他字段的串联,这看起来相对简单。但是我用来帮助创建以下字段(和)的case语法或语法是什么?if/whenGPA_TXTnewfield

逻辑是:每个 GPA 应该是#.#,每个新字段应该是:

name & "-" & GPA_TXT & (
    case where GPA_TXT > 3.3
        set newfield = newfield & 'GradeA',
    case where GPA_TXT >2.7 and GPA_TXT < 3.3
        set newfield = newfield & "GradeB",
    etc...
)

例如:

name         major     GPA(num) GPA_TXT   [newfield]
Bob          sci       2        02.0      Bob-sci-GradeC-02.0
Jane         chem      3.1      03.1      Jane-chem-GradeB-03.1
Charlie      phys      3.7      03.7      Charlie-phys-GradeA-03.7
Garfield     food      0        00.0      Garfield-food-GradeF-00.0

所以我想我在这里有两个问题:

  1. 如何创建 GPA TXT 字段。
  2. 如何编写case语句根据其他字段的值计算一个字段。

如果有人可以将我链接到带有示例或解释的资源,我将不胜感激!我正在查看文档,但没有示例就无法到达任何地方。

4

3 回答 3

17

重要提示:我会根据您当前的表创建一个视图并避免添加新列,因为它们会使您的架构非规范化。在这里阅读更多。

此外,我将对所有标识符使用小写名称以避免引用。

  • 要形成GPA_TXT字段,您可以使用to_char()函数:(to_char(gpa, 'FM09.0')FM避免结果字符串前面的空格);
  • 对于第二个字段,我会使用GPA而不是GPA_TXT用于数字比较。您可以在docs中查看有关CASE构造的更多信息,但该块可能是以下内容:

    CASE WHEN gpa >= 3.3 THEN 'A'
         WHEN gpa > 2.7 AND gpa < 3.3 THEN 'B'
         WHEN gpa > 0 THEN 'C'
         ELSE 'F' END
    

抱歉,我不知道每个 GPA 的成绩是如何分配的,请相应调整。

视图的结果查询可能是(也在SQL Fiddle上):

SELECT name,major,gpa,
       to_char(gpa, 'FM09.0') AS gpa_txt,
       name||'-'||major||'-Grade'||
  CASE WHEN gpa >= 3.3 THEN 'A'
       WHEN gpa > 2.7 AND gpa < 3.3 THEN 'B'
       WHEN gpa > 0 THEN 'C'
       ELSE 'F' END || '-' || to_char(gpa, 'FM09.0') AS adesc
  FROM atab;

要构建一个视图,只需CREATE VIEW aview AS在此查询之前添加。


编辑

如果您仍然要添加列,则以下内容应该可以解决问题:

ALTER TABLE atab ADD gpa_txt text, ADD adesc text;
UPDATE atab SET
    gpa_txt = to_char(gpa, 'FM09.0'),
    adesc = name||'-'||major||'-Grade'||
      CASE WHEN gpa >= 3.3 THEN 'A'
           WHEN gpa > 2.7 AND gpa < 3.3 THEN 'B'
           WHEN gpa > 0 THEN 'C'
           ELSE 'F' END || '-' || to_char(gpa, 'FM09.0');
于 2012-07-06T14:57:27.803 回答
5

我建议使用“生成”列,而不是冗余存储数据。它将占用更少的磁盘空间,这实际上可能比存储生成的值更快,并且肯定不会意外地与基础数据不同步。假设您喜欢@vyegorov 提供的格式,您可以创建这样的函数,使用表的记录类型(与表名匹配)作为输入:

CREATE FUNCTION adesc(rec atab)
  RETURNS text
  IMMUTABLE
  LANGUAGE SQL
AS $$
SELECT to_char($1.gpa, 'FM09.0') AS gpa_txt,
       $1.name||'-'||$1.major||'-Grade'||
  CASE WHEN $1.gpa >= 3.3 THEN 'A'
       WHEN $1.gpa > 2.7 AND $1.gpa < 3.3 THEN 'B'
       WHEN $1.gpa > 0 THEN 'C'
       ELSE 'F' END || '-' || to_char($1.gpa, 'FM09.0') AS adesc;
$$;

您需要使用关系限定符(表名或别名)来引用它。当这样的引用没有通过查找实际列来解决时,PostgreSQL 将寻找一个将表的记录类型作为其唯一参数的函数。所以你可以做这样的事情:

SELECT name, major, gpa, atab.adesc
  FROM atab;

这样一个“生成的列”可以在索引中用于快速搜索,如果那是你所追求的,就像adesc(atab).*.

于 2012-07-07T14:21:26.070 回答
0

这是从具有 3 列的表中返回值的查询:

select *
, to_char(gpa, '09.9') as gpa_text
, name || '-' || major || '-Grade' ||
case    when gpa between 3.5 and 4.0 then 'A'
    when gpa between 2.5 and 3.4 then 'B'
    when gpa between 1.5 and 2.4 then 'C'
    when gpa between 0.5 and 1.4 then 'D'
    else 'F' end
|| '-' || ltrim(to_char(gpa, '09.9')) as newfield
from students

这是工作代码,这是 Bob 的新字段“Bob-sci-GradeC-02.0”

我强烈建议您在数据库中没有文本列来保存数值的副本。我不太清楚为什么我需要 ltrim,格式化的字符串会有一个前导空格似乎很奇怪。

于 2012-07-06T15:27:40.987 回答