9

複数の列ごとにインデックスをインクリメントする組み込みの方法はありますか (つまり、トリガーや関数を必要とせずに) はありますか?

したがって、実行後:

INSERT INTO "table"
    ("month", "desc")
    VALUES
    (1, 'One thing')
,   (1, 'Another thing')
,   (1, 'Last task of the month')
,   (2, 'Last task of the month')
,   (2, 'Last task of the month')
,   (3, 'First of third month')

私のテーブルは次のようになります(「タスク」列に注意してください):

month    task    desc
1        1       One thing
1        2       Another thing
1        3       Last task of the month
2        1       First of second month
2        2       Second and last of second month
3        1       First of third month
4

2 に答える 2

11

simlpeSERIAL列をテーブルに追加して(順序を指定します)、次のように使用できます。

SELECT *, row_number() OVER (PARTITION BY month ORDER BY serial_column)
FROM table

これにより、希望する結果が得られます。

行を並べ替える必要がない場合は、次のことを試すことができます。

SELECT *, row_number() OVER (PARTITION BY month)
FROM table

詳細はこちら:row_number() OVER(...)

UPD仕組み:

タイプの列SERIALは、基本的に「自動増分」フィールドです。シーケンスから自動的に値を取得します。テーブルに行を挿入すると、次のようになります。

| MONTH | SERIAL_COLUMN |                     DESCRIPTION |
-----------------------------------------------------------
|     1 |             1 |                       One thing |
|     1 |             2 |                   Another thing |
|     1 |             3 |          Last task of the month |
|     2 |             4 |           First of second month |
|     2 |             5 | Second and last of second month |
|     3 |             6 |            First of third month |

重要なこと-次に追加されるすべての行の値は、前のすべての行よりもSERIAL_COLUMN 大きくなります。

次。しますrow_number() OVER (PARTITION BY month ORDER BY serial_column)

month1)すべての行を等しい(PARTITION BY month)でグループに分割します

serial_column2) (ORDER BY serial_column)の値で並べ替えます

`row_number() OVER3)すべてのグループで、手順2( )の順序を使用して行番号を割り当てます。

出力は次のとおりです。

| MONTH | SERIAL_COLUMN |                     DESCRIPTION | ROW_NUMBER |
------------------------------------------------------------------------
|     1 |             1 |                       One thing |          1 |
|     1 |             2 |                   Another thing |          2 |
|     1 |             3 |          Last task of the month |          3 |
|     2 |             4 |           First of second month |          1 |
|     2 |             5 | Second and last of second month |          2 |
|     3 |             6 |            First of third month |          1 |

の出力を変更するにはrow_number()、の値を変更する必要がありますSERIAL_COLUMN。たとえば、 aのSecond and last of second month前に配置すると、次のようFirst of second monthに値が変更されます。SERIAL_COLUMN

UPDATE Table1
SET serial_column = 5
WHERE description = 'First of second month';

UPDATE Table1
SET serial_column = 4
WHERE description = 'Second and last of second month';

クエリの出力が変更されます。

| MONTH | SERIAL_COLUMN |                     DESCRIPTION | ROW_NUMBER |
------------------------------------------------------------------------
|     1 |             1 |                       One thing |          1 |
|     1 |             2 |                   Another thing |          2 |
|     1 |             3 |          Last task of the month |          3 |
|     2 |             4 | Second and last of second month |          1 |
|     2 |             5 |           First of second month |          2 |
|     3 |             6 |            First of third month |          1 |

の正確な値は重要でSERIAL_COLUMNはありません。彼らは1か月のタスクの順序を設定するだけです。

私のSQLFiddleの例はここにあります。

于 2012-12-05T15:46:50.333 に答える
5

INSERTステートメントを挿入ごとに1行のデータに分割する場合は、PostgreSQLルールを使用できます。次の例は、ルールが書き込みをリレーション自体にリダイレクトできないように見えるという点で少し複雑です。これは通常、トリガーを使用して行われます。しかし、これがトリガーなしで可能かどうかを確認しているので、ここに行きます:

--drop table table_data cascade;
CREATE TABLE table_data (
  month integer not null,
  task integer not null,
  "desc" text
);
ALTER TABLE table_data add primary key (month, task);

CREATE VIEW "table" as 
 select month, task, "desc" from table_data;

CREATE OR REPLACE RULE calculate_task AS ON INSERT TO "table"
  DO INSTEAD
  INSERT into table_data (month, task, "desc") 
  VALUES (
  NEW.month, 
  (select coalesce(max(task),0) + 1 from table_data where month = NEW.month), 
  NEW."desc");

BEGIN;
INSERT INTO "table" ("month", "desc") VALUES (1, 'One thing');
INSERT INTO "table" ("month", "desc") VALUES (1, 'Another thing');
INSERT INTO "table" ("month", "desc") VALUES (1, 'Last task of the month');
INSERT INTO "table" ("month", "desc") VALUES (2, 'Last task of the month');
INSERT INTO "table" ("month", "desc") VALUES (2, 'Last task of the month');
INSERT INTO "table" ("month", "desc") VALUES (3, 'First of third month');
COMMIT;

select * from "table";

ノート

  • 「テーブル」でDELETE/UPDATEをサポートする必要がある場合は、それらのアクションごとにルールを追加することもできます。
  • 上記のBEGINandCOMMITブロックは、同じトランザクション内であっても、各行が独自のに分割されている限り、このメソッドが機能することを示すために使用されますINSERT
  • andのようないくつかの予約語を使用します。行ったように、必ず二重引用符で囲んでください。問題はありません。tabledesc

これがsqlfiddleの上記のコードです

于 2012-12-05T16:35:45.467 に答える