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

Posted

技术标签:

【中文标题】SQL select:一个表中的随机顺序值用于另一个表中的每一行【英文标题】:SQL select: random order values from one table for each row in another 【发布时间】:2012-07-05 15:23:17 【问题描述】:

我的数据库中有两个表:

(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) 的存储函数。为此,我正在考虑以下内容:

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

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

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

提前致谢。

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

【问题讨论】:

【参考方案1】:
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 和 window functions 都需要 PostgreSQL 8.4 或更高版本。

【讨论】:

是的,这行得通。不幸的是,live db 是 8.3,所以我不得不使用子查询。谢谢。【参考方案2】:

我认为以下方法会起作用:

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

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

【讨论】:

这不起作用,因为它每次都会随机选择,从而可能导致重复的短语。 我误会了。我以为你想要每个地方的随机短语。我会修改这个案例的解决方案。 第一个示例的性能影响是什么?我担心的是,尽管有LIMIT 1,它仍然会为每个place 运行整个表(当然,这里的结果集不是很大,但是...) 如果您对性能影响感兴趣,请查看:***.com/questions/5297396/…。 postgres 每次都应该读取表没有先验的原因,但这取决于数据库实现者。 是的,即使在我们过时的 8.3 上也能完美运行。谢谢!

以上是关于SQL select:一个表中的随机顺序值用于另一个表中的每一行的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:SELECT 查询以获取 DISTINCT 和 MAX 显示顺序值

如何将一个表中的随机值添加到另一个 Oracle SQL

复制表结构和内容到另一张表中的SQL语句

如何按特定顺序从 select 中执行 Oracle SQL 更新?

如何随机从数据库表中抽一条数据的SQL语句

sql查询语句:top n的用法