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以使其防弹 - 如果需要。

请注意,如果两个并发事务试图在同一时间添加相同的字符串,这里有一个非常小的竞争条件。可以肯定的是,您可以使用SERIALIZABLE事务。此相关问题下的更多信息和链接。

在 sqlfiddle 进行现场演示

于 2012-10-03T16:48:32.753 回答
1

如果它们都是单个字符,您可以这样做:

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

尽管如果字符串不止一个字符,那只会返回第一个字母的字符。

于 2012-10-03T16:15:37.317 回答
1

一个哈希值,比如md5name怎么样?

create table test (name text, hash text);

-- later

update test set hash = md5(name);

如果您需要将该 md5 文本转换为数字:Hashing a String to a Numeric Value in PostgresSQL

于 2012-10-03T16:16:23.837 回答
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 回答