在 Postgres 中随机分配数字
Random assigning of numbers in Postgres
我正在将员工编号映射到 13 位卡号。卡号应在 9353500001234 和 9353500501234 之间。
是否有任何内置函数可以将此范围内的随机数映射到员工编号。前雇员编号5001应该分配给9353500500934?另外赋值后,是否可以将员工号传给一个函数来赋值对应的卡号?
尽管理论上可以在域 1..500000 和 9353500001234...9353500501234 之间生成双射函数,但实际上,最简单的方法就是创建一个映射(在数学意义上),并且SELECT
来自它。
也就是说,您首先要创建一个 table 来存储 (employee_id, card_number)
:
对
CREATE TABLE employee_card
(
employee_id INTEGER NOT NULL PRIMARY KEY,
card_number BIGINT NOT NULL UNIQUE
) ;
鉴于 table,我们用所有可能的 employee_id 和 card_number 填充它,随机洗牌 card_number。我们通过 generate_series
set returning function, together with row_number()
, using a random()
ly sorted window (over clause):
来做到这一点
INSERT INTO employee_card (employee_id, card_number)
SELECT
row_number() over(order by random()) AS employee_id, employee_card
FROM
-- generate card_numbers
generate_series(9353500001234, 9353500501234) AS s(employee_card)
我们添加了一些索引以最佳方式获取数据:
-- Indexes to ease retrieving the data from this table
CREATE INDEX idx_employee_card_card_number ON employee_card(card_number, employee_id);
CREATE INDEX idx_employee_card_employee_id ON employee_card(employee_id, card_number);
VACUUM ANALYZE employee_card;
此时,如果要有两个函数,就是前面table的SELECT
:
-- Get card_number given employee_id
CREATE OR REPLACE FUNCTION card_number_from_employee_id(_employee_id integer)
RETURNS BIGINT
IMMUTABLE
STRICT
LANGUAGE SQL
AS
$$
SELECT card_number FROM employee_card WHERE employee_id = _employee_id ;
$$ ;
-- Get employee_id given card_number
CREATE OR REPLACE FUNCTION employee_id_from_card_number(_card_number BIGINT)
RETURNS INTEGER
IMMUTABLE
STRICT
LANGUAGE SQL
AS
$$
SELECT employee_id FROM employee_card WHERE card_number = _card_number ;
$$ ;
您现在可以测试几个 employee_id 并检索卡号。卡号应该是随机的:
SELECT
employee_id, card_number_from_employee_id(employee_id)
FROM
generate_series(10001, 10010) AS s(employee_id) ;
employee_id | card_number_from_employee_id
----------: | ---------------------------:
10001 | 9353500008121
10002 | 9353500281438
10003 | 9353500124657
10004 | 9353500369382
10005 | 9353500238058
10006 | 9353500205141
10007 | 9353500297414
10008 | 9353500286020
10009 | 9353500219563
10010 | 9353500443892
同时测试反向功能:
SELECT
card_number, employee_id_from_card_number(card_number)
FROM
generate_series(9353500001234 + 1023, 9353500001234 + 1023 + 9) AS s(card_number);
card_number | employee_id_from_card_number
------------: | ---------------------------:
9353500002257 | 46754
9353500002258 | 25124
9353500002259 | 481462
9353500002260 | 99475
9353500002261 | 173732
9353500002262 | 171043
9353500002263 | 245192
9353500002264 | 418200
9353500002265 | 76374
9353500002266 | 251095
您可以在 dbfiddle here
查看所有设置和功能
我正在将员工编号映射到 13 位卡号。卡号应在 9353500001234 和 9353500501234 之间。
是否有任何内置函数可以将此范围内的随机数映射到员工编号。前雇员编号5001应该分配给9353500500934?另外赋值后,是否可以将员工号传给一个函数来赋值对应的卡号?
尽管理论上可以在域 1..500000 和 9353500001234...9353500501234 之间生成双射函数,但实际上,最简单的方法就是创建一个映射(在数学意义上),并且SELECT
来自它。
也就是说,您首先要创建一个 table 来存储 (employee_id, card_number)
:
CREATE TABLE employee_card
(
employee_id INTEGER NOT NULL PRIMARY KEY,
card_number BIGINT NOT NULL UNIQUE
) ;
鉴于 table,我们用所有可能的 employee_id 和 card_number 填充它,随机洗牌 card_number。我们通过 generate_series
set returning function, together with row_number()
, using a random()
ly sorted window (over clause):
INSERT INTO employee_card (employee_id, card_number)
SELECT
row_number() over(order by random()) AS employee_id, employee_card
FROM
-- generate card_numbers
generate_series(9353500001234, 9353500501234) AS s(employee_card)
我们添加了一些索引以最佳方式获取数据:
-- Indexes to ease retrieving the data from this table
CREATE INDEX idx_employee_card_card_number ON employee_card(card_number, employee_id);
CREATE INDEX idx_employee_card_employee_id ON employee_card(employee_id, card_number);
VACUUM ANALYZE employee_card;
此时,如果要有两个函数,就是前面table的SELECT
:
-- Get card_number given employee_id
CREATE OR REPLACE FUNCTION card_number_from_employee_id(_employee_id integer)
RETURNS BIGINT
IMMUTABLE
STRICT
LANGUAGE SQL
AS
$$
SELECT card_number FROM employee_card WHERE employee_id = _employee_id ;
$$ ;
-- Get employee_id given card_number
CREATE OR REPLACE FUNCTION employee_id_from_card_number(_card_number BIGINT)
RETURNS INTEGER
IMMUTABLE
STRICT
LANGUAGE SQL
AS
$$
SELECT employee_id FROM employee_card WHERE card_number = _card_number ;
$$ ;
您现在可以测试几个 employee_id 并检索卡号。卡号应该是随机的:
SELECT
employee_id, card_number_from_employee_id(employee_id)
FROM
generate_series(10001, 10010) AS s(employee_id) ;
employee_id | card_number_from_employee_id ----------: | ---------------------------: 10001 | 9353500008121 10002 | 9353500281438 10003 | 9353500124657 10004 | 9353500369382 10005 | 9353500238058 10006 | 9353500205141 10007 | 9353500297414 10008 | 9353500286020 10009 | 9353500219563 10010 | 9353500443892
同时测试反向功能:
SELECT
card_number, employee_id_from_card_number(card_number)
FROM
generate_series(9353500001234 + 1023, 9353500001234 + 1023 + 9) AS s(card_number);
card_number | employee_id_from_card_number ------------: | ---------------------------: 9353500002257 | 46754 9353500002258 | 25124 9353500002259 | 481462 9353500002260 | 99475 9353500002261 | 173732 9353500002262 | 171043 9353500002263 | 245192 9353500002264 | 418200 9353500002265 | 76374 9353500002266 | 251095
您可以在 dbfiddle here
查看所有设置和功能