我正试图想出一种方法,从大约6人的大型数据集中将两个人分配到一起。我正在玩postgres中的random()函数,但没有运气。我可以访问postgres或oracle,无论哪个更容易实现。 例如,如果我有6个名字,我想使用这些6个名称并使用某种随机查询将它们分配给彼此:
输出将是:
原始名称|匹配
非常感谢任何帮助!
谢谢。
答案 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中解决这个问题不是一个容易的问题。