3

我的数据库中有两个表:

(1) 短语:

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

(2) 地点:

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

PHRASES的行数至少与PLACES. 我需要以这样一种方式加入这两个表,以便为每个表选择所有places phrase- 但短语需要随机分布在不同的地方。整个places表并不太大:可能大约有 3-4 千行,但是上面会有一个附加WHERE子句,最多将输出限制为大约 200 个位置。

理想情况下,我希望它包含在一个 SQL 语句中,但到目前为止,我还无法理解这一点。因此,第二个选项是返回一行的存储函数(int, varchar, varchar)。为此,我正在考虑以下内容:

  1. 以随机顺序将所有短语选择到 varchar 数组中
  2. 循环遍历一次取一个的位置并将其与数组中的下一个短语一起返回

不知何故,这在我看来效率很低,但我想不出更好的办法。

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

提前致谢。

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

4

2 回答 2

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,但也可以使用子查询来完成。CTE窗口函数都需要 PostgreSQL 8.4 或更高版本。

于 2012-07-05T23:24:19.480 回答
0

我认为以下将起作用:

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

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

如果您只想随机排列短语和地点,可以使用 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

这会按地点(或任何领域都可以)对地点进行排序。它随机化短语,并加入结果行号。

于 2012-07-05T15:32:46.040 回答