与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
答案 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下的更多信息和链接。
答案 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');
,则排名会发生变化。