14

他のフィールドを連結した新しいフィールド(または2つ)をテーブルに作成したいのですが、これは比較的簡単に思えます。しかし、次のフィールド(、、および)の作成を支援するために使用する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

だから私はここに2つの質問があると思います:

  1. GPATXTフィールドを作成する方法。
  2. 他のフィールドの値に従ってフィールドを計算するcaseステートメントの記述方法。

誰かが私を例のあるリソースにリンクしたり、説明したりできるなら、私はそれを大いに感謝します!私はドキュメントを調べていますが、例がなければどこにも行きません。

4

3 に答える 3

17

重要な注意:現在のテーブルに基づいてビューを作成し、スキーマを非正規化するため、新しい列を追加しないようにします。詳細はこちらをご覧ください

また、qoutingを回避するために、すべての識別子に小文字の名前を使用します。

  • GPA_TXTフィールドを形成するには、to_char()関数を使用できますto_char(gpa, 'FM09.0'):(FM結果の文字列の前のスペースを回避します);
  • 2番目のフィールドには、数値比較GPAではなく使用します。ドキュメントで構成GPA_TXTについて詳しく確認できますが、ブロックは次のようになります。 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 に答える