【问题标题】:SQL: how to get random number of rows from one table for each row in anotherSQL:如何从一个表中为另一个表中的每一行获取随机数的行
【发布时间】:2012-11-23 11:54:14
【问题描述】:

我有两个数据不相关的表 对于表 A 中的每一行,我想要例如表 B 中的 3 个随机行

使用游标相当容易,但速度非常慢

那么我怎样才能在单个语句中表达这一点以避免 RBAR 呢?

【问题讨论】:

  • 您使用的是哪个 DBMS?甲骨文? PostgreSQL? DB2?

标签: sql sql-server-2008 random


【解决方案1】:

假设tableB有整数代理键,试试

 Declare @maxRecs integer = 11 -- Maximum number of b records per a record
 Select a.*, b.*
 From tableA a Join tableB b
     On b.PKColumn % (floor(Rand() * @maxRecs)) = 0

【讨论】:

    【解决方案2】:

    如果你有一个预先知道的固定数字(比如3),那么:

    select a.*, b.*
    from a cross join
         (select top 3 * from b) b
    

    如果你想为“a”中的每一行从“b”中随机数行,那么在 SQL Server 中这个问题就有点困难了。

    【讨论】:

    • 第二个问题应该是top 3 *而不是top 3,但我无法编辑答案。
    • 并且子查询中应该有一个order by newid()。为什么我在这里发帖时总是出错?
    • 这会在a 中从b 获得三个不同“随机”行,还是总是使用相同的三行(因为内部@ 987654327@...)。我有一种感觉,OP 可能每次都要换 3 行不同的行。
    • @Gordon Linoff:在 meta 上提问(关于连接或发布问题)
    • @ypercube 。 . .谢谢你的建议,但是这个问题已经被问过了,似乎没有一个合理的答案。
    【解决方案3】:

    这是一个如何做到这一点的示例,代码是自包含的,复制并按 F5 ;)

    -- create two tables we can join 
    DECLARE @datatable TABLE(ID INT)
    DECLARE @randomtable TABLE(ID INT)
    
    -- add some dummy data
    DECLARE @i INT = 1
    WHILE(@i < 3) BEGIN
        INSERT INTO @datatable (ID) VALUES (@i)
        SET @i = @i + 1
    END 
    
    SET @i = 1
    WHILE(@i < 100) BEGIN
        INSERT INTO @randomtable (ID) VALUES (@i)
        SET @i = @i + 1
    END 
    
    --The key here being the ORDER BY newid() which makes sure that 
    --the TOP 3 is different every time
    SELECT 
        d.ID AS DataID
        ,rtable.ID RandomRow
    FROM @datatable d
    LEFT JOIN (SELECT TOP 3 * FROM @randomtable ORDER BY newid()) as rtable ON 1 = 1
    

    这是一个输出示例

    【讨论】:

      【解决方案4】:

      要获取0到(N-1)之间的随机数,可以使用。

      abs(checksum(newid())) % N
      

      这意味着获得正值 1-N,你使用

      1 + abs(checksum(newid())) % N
      

      注意:RAND() 不起作用 - 每个查询批次都会对其进行一次评估,并且对于 tableA 的所有行都使用相同的值。

      查询:

      SELECT *
        FROM tableA A
        JOIN (select *, rn=row_number() over (order by newid())
                from tableB) B ON B.rn <= 1 + abs(checksum(newid())) % 9
      

      (假设您希望每个 A 最多随机包含 9 行 B)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-04
        • 2020-12-11
        • 2015-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多