Sql oracle中的随机连接

Sql oracle中的随机连接,sql,oracle,join,random,Sql,Oracle,Join,Random,我有三个查询,我希望结果行由这些查询的条目组成,这些条目彼此随机连接 我不想合并结果,而是以或多或少的随机方式将它们合并(原始分布可以保留,也可以在所有结果中统一) 我尝试了以下方法: select * from ( SELECT street, number FROM Addresses WHERE valid = '1' order by Dbms_Random.Value ) q1 , ( select prename from

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

我不想合并结果,而是以或多或少的随机方式将它们合并(原始分布可以保留,也可以在所有结果中统一)

我尝试了以下方法:

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
并将其应用于笛卡尔乘积的结果是非常低效的,因为表非常大,尤其是它们的笛卡尔乘积。

您遇到的问题是,虽然每个表都是随机排序的,您仍然有一个笛卡尔乘积,这样顶部行的前两列的值相同,而最后一列的值不同

如果选择伪列ROWNUM(需要将其别名为eg row_number),然后在row_number上连接3个表,那么应该从3个表中获得数据的随机组合


但总行数将被限制为与最小表中的行数相等。

您可以将Dbms_Random.Value移动到子查询中的一列,并用它连接。
这将使结果随机化,并通过消除
顺序:

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
;
(另见)

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

请注意,此解决方案重用每个子查询的结果,因此,例如,prename可能会被多次使用或根本不使用,但在原始笛卡尔联接中也是如此。

确保唯一性,如果您需要的话。

科林·哈特诊断了这个问题,并建议使用rownum解决问题。但解决方案比这稍微复杂一些,因为如果ROWNUM和ORDER BY都出现在同一个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)
;
此解决方案将始终返回与最小表中的行数相等的随机行数。任何行都不会被多次使用。这是你的电话号码


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

目前您正在检索笛卡尔积。这就是你想要的吗?比如,如果每个表有10行,那么您是否希望结果集以随机顺序包含所有1000个连接行?还是只需要10行?要查找多少值?每张桌子有多大?谢谢你的回答。结果总数不应该是笛卡尔积的大小,而可以是最小表和最大表之间的某个地方。一个选项卡中的行可以多次出现。+1,但解决方案比您描述的要复杂一些。请参阅,OP需要澄清他是否希望值只使用一次。返回的行数是随机的。从理论上讲,这种解决方案有时可能不会返回任何行,尽管这是一种极低的风险,除非随机数限制远远大于最小表中的行数。