将特定数量的行从一个 table 连接到另一个行的单行

Join specific number of rows from one table to a single row of another one

我目前正在生成随机数据,但我不确定如何执行这一部分。 我有两个 table。我有一个实体 table 和一个组 table。两个 table 都有唯一的标识符 (guid)。我的目标是创建一个 table 映射,将实体 X 次匹配到单个组。

例如,假设我有 10k 个实体和 100 个组,我想创建 1k 个映射。我需要为每个组 (1000/100) 创建 10 个映射。我可以继续创建一个 while 循环,只得到 10 个随机实体,但效率不高,我想避免这种情况。我也想过cross join然后把结果缩减到1k,但是我希望每组有完全相同数量的映射。

有没有办法通过单个查询来完成此操作?

这是一个例子,假设我有这个 Group tableEntity Table


+---------+
| GroupId |
+---------+
| G1      |
| G2      |
| G3      |
+---------+
+----------+
| EntityId |
+----------+
| E1       |
| E2       |
| E3       |
| E4       |
| E5       |
| E6       |
| E7       |
| E8       |
| E9       |
| E10      |
+----------+

I would like to get 6 mappings (so each group needs 2 mappings). Here is an example of what I could get:

+---------+----------+
| GroupId | EntityId |
+---------+----------+
| G1      | E2       |
| G1      | E4       |
| G2      | E9       |
| G2      | E10      |
| G3      | E2       |
| G3      | E5       |
+---------+----------+


这听起来很适合 NTILE

首先使用 ROW_NUMBER() on the Groups table to generate sequential "group numbers" (sort by NewID() 作为 相对 随机顺序):

GroupId | GroupNum
:------ | -------:
G3      |        1
G2      |        2
G1      |        3

然后使用 NTILE()Entity 行分配到所需数量的组中:

E1  | GroupNum
:-- | -------:
E2  |        1
E10 |        1
E3  |        1
E4  |        1
E1  |        2
E6  |        2
E5  |        2
E7  |        3
E8  |        3
E9  |        3

最后在“组号”上将结果合并在一起:

SQL:

DECLARE @NumOfGroups INT;

SET @NumOfGroups = ( SELECT COUNT(*) FROM Groups );

SELECT e.[E1], g.GroupId
FROM  (
        SELECT  *, NTILE(@NumOfGroups) OVER(ORDER BY NEWID()) AS GroupNum 
        FROM    Entities 
      ) 
      AS e 
      INNER JOIN 
      (
         SELECT *, ROW_NUMBER() OVER(ORDER BY NEWID()) AS GroupNum
         FROM   Groups
      )  
      AS g ON g.GroupNum = e.GroupNum
ORDER BY e.GroupNum, e.E1
GO

结果:

E1 GroupId
E1 G1
E3 G1
E5 G1
E8 G1
E2 G3
E7 G3
E9 G3
E10 G2
E4 G2
E6 G2

db<>fiddle here

注意:如果 Entity 行少于 Groups,显然这种方法将不起作用,但这听起来不像是这里的问题