PostgreSQL中的因子(字符串)到数字

时间:2012-10-03 15:58:47

标签: sql postgresql types

this类似,是否可以在PostgreSQL中将String字段转换为Numeric。例如,

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 个答案:

答案 0 :(得分: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
);

然后你会输入这样的新字符串:
Data-modifying 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.如果不存在,则插入一个新行,从计数开始。

UNIQUE还会自动在列string.string上添加索引,从而为此查询带来最佳效果。

UPDATE / DELETE添加额外的逻辑(触发器?),以便在需要时进行防弹。

注意,如果两个并发事务尝试在同一时刻添加相同的字符串,则此处存在超小的竞争条件。绝对确定,您可以使用SERIALIZABLE次交易。此this related question下的更多信息和链接。

Live demo at sqlfiddle

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

name的哈希值such as md5怎么样?

create table test (name text, hash text);

-- later

update test set hash = md5(name);

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

答案 3 :(得分:1)

您的请求中显示的确切案例可以使用dense_rank window function

生成
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');,则排名会发生变化。