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
一样多。我需要以这样一种方式加入这两个表,以便为每个表选择所有 place
s 和一个 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 显示顺序值