随机化两个数据集

时间:2018-02-14 19:23:20

标签: oracle postgresql

我正试图想出一种方法,从大约6人的大型数据集中将两个人分配到一起。我正在玩postgres中的random()函数,但没有运气。我可以访问postgres或oracle,无论哪个更容易实现。 例如,如果我有6个名字,我想使用这些6个名称并使用某种随机查询将它们分配给彼此:

  1. 比利
  2. 鲍勃
  3. 萨姆
  4. 约翰
  5. 亚历
  6. 输出将是:

    原始名称|匹配

    1. 比利|亚历
    2. 鲍勃|乔
    3. 乔|约翰
    4. Sam |鲍勃
    5. 约翰|比利
    6. Alex |萨姆
    7. 非常感谢任何帮助!

      谢谢。

1 个答案:

答案 0 :(得分:1)

在postgres中,您可以在随机数上生成row_number(),然后加入。这很好而且速度很快,但它可能会让人们与自己结识:

SELECT t1.name, t2.name
FROM (SELECT row_number() OVER (ORDER BY random()) as id, name FROM table) t1
INNER JOIN (SELECT row_number() OVER (order by random()) as id, name FROM table) t2 
     ON t1.id = t2.id;

这是一种使用笛卡尔积的方法,该方法是将表连接到自身的结果。如果数据很大,这不是一个很好的解决方案,因为有一个中间结果集是(N *(N - 1))行,但没有人会与自己匹配:

SELECT name1,
    name2
FROM (
    SELECT t1.NAME name1,
        t2.NAME name2,
        row_number() OVER (PARTITION BY t1.NAME ORDER BY random()) AS rn
    FROM yourtable t1,
        yourtable t2
    WHERE t1.NAME <> t2.NAME
    ) subquery
WHERE rn = 1;

这是两者的混合体。在一系列随机生成的id上将表连接到自身,同时指定名称不匹配。对于t2中的每个名称,中间结果集将从t1中随机选择1-3个名称。然后我们随便抓一个。这有一个中间结果集,总是小于(N * 3)记录,这不是太糟糕。

UPDATE :但是,这会多次匹配同一个人...将它保留在这里,以防它产生如此好的想法,以防止这种情况发生的INNER JOIN。

WITH randnames AS 
(
    SELECT row_number() OVER (ORDER BY random()) AS id,
        NAME
    FROM yourtable
)
SELECT name1, name2
FROM (
    SELECT t1.NAME name1,
        t2.NAME name2,
        ROW_NUMBER() OVER (PARTITION BY t1.NAME ORDER BY 1) AS rn
    FROM randnames t1
      INNER JOIN randnames t2
        ON t1.NAME <> t2.NAME
            AND t2.id BETWEEN t1.id - 1 AND t1.id + 1
    ) subquery
WHERE rn = 1;

我觉得可能有一些更漂亮的方法可以做到这一点,但在被问到这个问题一小时之后完全没有回答这个问题表明在SQL中解决这个问题不是一个容易的问题。