SQL select:一个表中的随机顺序值,用于另一个表中的每一行

时间:2012-07-05 15:23:17

标签: sql postgresql stored-procedures stored-functions

我的数据库中有两个表:

(1)PHRASES:

t_phrase
========
I like
They prefer
...
Somebody else wants

(2)地点:

n_id   t_place
====   =======
1      London
2      Paris
...
N      New York

PHRASES的行数至少与PLACES一样多。我需要加入这两个表格,以便为每个表格选择所有placephrase - 但短语需要在各个地方随机分布。整个places表不是太大:也许,大约3-4,000行,但是它上面会有一个额外的WHERE子句,它将输出限制在最多约200个位置。 / p>

理想情况下,我希望这是一个SQL语句,但到目前为止,我还没有能够理解这一点。因此,第二个选项是返回(int, varchar, varchar)行的存储函数。为此,我想到的是:

  1. 以随机顺序选择所有短语到varchar数组
  2. 循环播放一次一个地方并将其与数组中的下一个短语一起返回
  3. 在某种程度上,这对我来说效率很低,但我无法想出更好的东西。

    你能提出更好的建议吗?或者,甚至更好,一个语句SQL,也许?

    提前致谢。

    编辑:请注意,不应在结果集中重复这些短语。总有至少与地方一样多的短语。

2 个答案:

答案 0 :(得分:2)

WITH p AS (
    SELECT place, row_number() OVER () AS rn
    FROM   t_place
    WHERE  <some condition>
    )
    , ph AS (
    SELECT phrase, row_number() OVER (ORDER BY random()) AS rn
    FROM   t_phrase
    )
SELECT ph.phrase, p.place
FROM   p
JOIN   ph USING (rn);

如果你在两个表上施加一个真正的随机顺序,它将不再随机,它只会变慢。我对短语强加了随机顺序,因为:

  

总有至少与地方一样多的短语。

需要使用更大的设置来完成,以免某些非随机部分被切断。另一方面,对于较小的集合(地点),任何数字序列没有间隙是好的,所以我选择最快的方式。

我的示例使用CTE,但也可以使用子查询来完成。 CTEwindow functions都需要PostgreSQL 8.4或更高版本。

答案 1 :(得分:0)

我认为以下内容可行:

select (select phrase from phrases order by random() limit 1),
       place
from places

应该为每一行调用select中的select,因此每次都应该返回一个不同的值。

如果您只想随意排列短语和地点,可以使用Windows功能:

select ph.phrase, p.place
from (select place, row_number() over (order by place) as seqnum
      from places p
     ) p join
     (select phrase, row_number() over (order by random()) as seqnum
      from phrases
     ) ph 
     on p.seqnum = ph.seqnum

按地点(或任何字段都可以)对地点进行排序。它随机化短语,并加入生成的行号。