1

我有三个查询,我希望由这些查询的条目组成的结果行随机连接在一起。

我不想合并结果,而是以或多或少随机的方式加入它们(可以保留原始分布,或者可以在所有人之间统一)。

我尝试了以下方法:

select * 
from 
(
    SELECT street, number 
    FROM Addresses 
    WHERE valid = '1' 
    order by Dbms_Random.Value
) q1 ,
(
    select prename 
    from person 
    order by Dbms_Random.Value
) q2 , 
(
    select surname 
    from person 
    order by Dbms_Random.Value
) q3

然而,我的结果集看起来一点也不随机:

Main street, 1, Andre, Smith
Main street, 1, Andre, Warnes
Main street, 1, Andre, Jackson
Main street, 1, Andre, Macallister

从查询中删除ORDER BY并将其应用于笛卡尔积的结果是非常低效的,因为表很大,尤其是它们的笛卡尔积。

4

3 回答 3

5

Colin 't Hart 诊断出问题,并建议使用rownum 来解决问题。但是解决方案稍微复杂一点,因为如果 ROWNUM 都出现在同一个 SELECT 中,那么它们会在 ORDER BY 之前分配。解决方案是添加一个额外的子查询级别。

with randomAddress as(
  select rownum id, street, num from (
    select * from addresses where valid=1 order by dbms_random.random
  )
),
randomPrename as(
  select rownum id, prename from(
    select * from person order by dbms_random.random
  )
),
randomSurname as(
  select rownum id, surname from(
    select * from person order by dbms_random.random
  )
)
select street, num, prename, surname
  from randomAddress
  join randomPrename using(id)
  join randomSurname using(id)
;

此解决方案将始终返回与最小表中的行数相等的随机行数。任何行都不会被使用超过一次。这是SQL 小提琴

GWu 解决方案返回的行数将根据分配相同随机数的行数而有所不同。有些行可能会被多次使用,而其他行则根本不用。您还应该知道要使用该解决方案的表中有多少行。

于 2012-07-24T16:37:01.310 回答
3

您可以将 Dbms_Random.Value 移动到子查询中的列并通过它加入。
这将随机化结果并摆脱order by

select * 
  from 
        (
            SELECT street, snumber, ROUND(Dbms_Random.Value(1,10)) n
              FROM Addresses 
             WHERE valid = '1' 
        ) q1 ,
        (
            select prename, ROUND(Dbms_Random.Value(1,10)) n 
              from person 
        ) q2 , 
        (
            select surname, ROUND(Dbms_Random.Value(1,10)) n
              from person 
        ) q3
where q1.n = q2.n
  and q2.n = q3.n
;

(另见http://www.sqlfiddle.com/#!4/a26d0/9

10中的值ROUND(Dbms_Random.Value(1,10))只是一个假设,将其更改为您的预期或可用记录数。

请注意,此解决方案会重用每个子查询的结果,因此例如 prename 可能会多次使用或根本不使用,但在原始笛卡尔连接中也是如此。
如果您需要, Colin 的方法可确保唯一性。

于 2012-07-24T16:15:36.767 回答
2

您遇到的问题是,虽然每个表都是随机排序的,但您仍然有一个笛卡尔积,因此顶部行的前两列将具有相同的值,只有最后一列不同。

如果您选择伪列 ROWNUM(您需要将其别名为例如 row_number),然后在 row_number 上加入 3 个表,您应该从 3 个表中获得数据的随机组合。

但是您将被限制为等于最小表中的行数的总行数。

于 2012-07-24T15:17:42.937 回答