如何在SQL

时间:2017-05-16 18:32:35

标签: sql sql-server

我有两个单列表,A和B.我想创建一个新表,其中A的每个元素与来自B的3个随机元素的样本配对,即:

表A:

A1  
A2  
A3   

表B:

B1  
B2  
B3  
...  
B100

结果表C:

A1 B51  
A1 B63  
A1 B17   
A2 B62    
A2 B13    
A2 B17  
A3 B1  
A3 B69  
A3 B78

对于每个A,B的值是随机的。重复/重叠对于不同的As是好的,但对于给定的A不是(即每个A必须与B的3个唯一元素配对,但是不同的As可以具有相同的元素来自B;也就是说,不同的As应该极不可能有相同的B组)。有没有办法在没有对A?

的元素使用for循环的情况下执行此操作

3 个答案:

答案 0 :(得分:3)

我认为最简单的方法可能是outer apply

select a.*, b.*
from a outer apply
     (select top 3 b.*
      from b
      where b.id <> a.id   -- just needed to prevent correlation "optimization"
      order by newid()
     ) b;

我强调“简单”。对于较大的b表,Ross的解决方案可能更快。

答案 1 :(得分:0)

这样做会但是速度不是很快。假设F1是A的主键(或者至少是A的一些唯一键),F2是你想要的B值(主键或不是主键):

WITH X AS (
   SELECT A.F1,  ROW_NUMBER() OVER (ORDER BY A.F1) AS N
   FROM A
), Y AS (
   SELECT B.F2, ROW_NUMBER() OVER (ORDER BY NEWID()) AS N
   FROM B
) 
SELECT A.F1, B.F2
FROM X INNER JOIN Y ON Y.N BETWEEN (X.N-1)*10+1 and ((X.N)*10)

编辑:修复一个错误。现在使用Y.N = 1..10表示X.N = 1,Y.N = 11..20表示X.N = 2,等等。

答案 2 :(得分:0)

我相信这有效:

    ;
    WITH    RandomBs
              AS ( SELECT c.ClientId AS val
                    ,   ROW_NUMBER() OVER ( ORDER BY ( SELECT NEWID() ) ) rn
                    FROM Clients c),
            A AS ( SELECT DO.OrganizationId
                    ,   ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL ) ) rn
                    FROM Organizations DO)
        SELECT *
            FROM A
                CROSS APPLY ( SELECT val
                                FROM RandomBs
                                WHERE rn BETWEEN ( ( ( A.rn - 1 ) * 10 ) + 1 ) AND ( (A.rn * 10) ) ) x