1

これと同様に、PostgreSQL で文字列フィールドを数値に変換することは可能ですか。例えば、

create table test (name text);

insert into test (name) values ('amy');
insert into test (name) values ('bob');
insert into test (name) values ('bob');
insert into test (name) values ('celia');

であるフィールドを追加します

 name  | num
-------+-----
 amy   | 1
 bob   | 2
 bob   | 2
 celia | 3
4

4 に答える 4

4

すべての中で最も効果的な「ハッシュ」関数はserial主キーです。質問で希望したような一意の番号を提供します。

このデモでは、重複も扱います。

CREATE TEMP TABLE string (
  string_id serial PRIMARY KEY
 ,string    text NOT NULL UNIQUE    -- no dupes
 ,ct        int NOT NULL DEFAULT 1  -- count instead of dupe rows
);

次に、次のように新しい文字列を入力します:
(データ変更 CTEには PostgreSQL 9.1 以降が必要です。)

WITH x AS (SELECT 'abc'::text AS nu)
   , y AS (
   UPDATE string s
   SET    ct = ct + 1
   FROM   x
   WHERE  s.string = x.nu
   RETURNING TRUE
   )
INSERT INTO string (string)
SELECT nu
FROM   x
WHERE NOT EXISTS (SELECT 1 FROM y);

文字列nuが既に存在する場合、カウント ( ct) は 1 ずつ増えます。存在しない場合は、カウント 1 から始まる新しい行が挿入されます。

またUNIQUE、列にインデックスがstring.string自動的に追加されるため、このクエリのパフォーマンスが最適化されます。

UPDATE/に追加のロジック (トリガー ?) を追加DELETEして、これを防弾にします - 必要に応じて。

ここで、2 つの同時トランザクションが同じ文字列を同時に追加しようとすると、非常に小さな競合状態が発生することに注意してください。確かに、SERIALIZABLEトランザクションを使用できます。この関連する質問の下の詳細情報とリンク。

sqlfiddle でのライブ デモ

于 2012-10-03T16:48:32.753 に答える
1

リクエストに示されている正確なケースは、dense_rankウィンドウ関数を使用して生成できます。

regress=# SELECT name, dense_rank() OVER (ORDER BY name) FROM test;
 name  | dense_rank 
-------+------------
 amy   |          1
 bob   |          2
 bob   |          2
 celia |          3
(4 rows)

したがって、各行に数値を追加すると、次のようなことができます。

ALTER TABLE test ADD COLUMN some_num integer;

WITH gen(gen_name, gen_num) AS 
   (SELECT name, dense_rank() OVER (ORDER BY name) FROM test GROUP BY name)
UPDATE test SET some_num = gen_num FROM gen WHERE name = gen_name;

ALTER TABLE test ALTER COLUMN some_num SET NOT NULL;

ただし、ハッシュを使用するか、生成されたキーを割り当てる方がはるかに賢明だと思います。私はあなたの例が達成できることを示しているだけです。

このアプローチの最大の問題は、新しいデータを挿入するのが面倒なことです。これは(あなたの例が示すように)ランキングなので、あなたがINSERT INTO test (name) VALUES ('billy');そうするとランキングが変わります。

于 2012-10-04T03:21:21.387 に答える
1

のmd5 などのハッシュはどうnameですか?

create table test (name text, hash text);

-- later

update test set hash = md5(name);

その md5 テキストを数値に変換する必要がある場合: PostgresSQL で文字列を数値にハッシュする

于 2012-10-03T16:16:23.837 に答える
1

それらがすべて単一の文字である場合、これを行うことができます:

ALTER TABLE test ADD COLUMN num int;
UPDATE test SET num = ascii(name);

ただし、文字列が複数の文字である場合、最初の文字の文字のみが返されます。

于 2012-10-03T16:15:37.317 に答える