在Postgres中随机分配数字

时间:2017-07-30 11:58:34

标签: postgresql postgresql-9.3 postgresql-9.5

我将员工编号映射到13位卡号。卡号应在9353500001234和9353500501234之间的范围内。

是否有任何内置功能可将此范围内的随机数映射到员工编号。应将员工编号5001分配给9353500500934?一旦分配,是否可以将员工编号传递给功能以获取相应的卡号?

1 个答案:

答案 0 :(得分:2)

虽然理论上可以在域1..500000和9353500001234 ... 9353500501234之间生成双射函数,但实际上,最简单的方法就是创建一个地图(在数学意义上)和{{ 1}}来自它。

也就是说,您首先要创建一个表来存储SELECT

(employee_id, card_number)

鉴于该表,我们用所有可能的employee_id和card_number填充它,随机改组card_numbers。我们通过generate_series设置返回函数和row_number(),使用random()已排序window (over clause)来实现这一点:

CREATE TABLE employee_card
(
    employee_id INTEGER NOT NULL PRIMARY KEY,
    card_number BIGINT NOT NULL UNIQUE 
) ;

我们添加一些索引以最佳方式获取数据:

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; 个:

SELECT

您现在可以测试一些employee_ids,并检索卡号。卡号应该是随机的:

-- 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 | 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 
    employee_id, card_number_from_employee_id(employee_id)
FROM
    generate_series(10001, 10010) AS s(employee_id) ;
  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

检查所有设置和功能