T-SQL 自加入 Table 与外部 Table 分组

T-SQL Self Join Table with External Table Grouping

期望的结果是根据第二组对第一组进行分组。有一群人要配给其他人,隔着"rooms"所以每个房间统一使用。因此,如果有 5 个人和 7 个房间,则有 20 种组合,因此每个房间的使用次数不会超过 3 次(切线:每个房间按顺序使用,因此不会有一个人一次出现在多个地方的危险)。每组有 3 对,但随着添加额外的组行,每组的对数应该减少;如果删除了额外的组行,则每组的对数应该增加。如果我不是在 Sets 中思考,它感觉就像一个 RBAR 操作,因为我只希望每个房间用作人数组合除以组数 - 20 个组合/7 个组 = 每组 3 个组合,但是 20组合 / 5 组 = 每组 4 种组合。

结果集目前看起来像这样:

person1    person2
person1    person3
person1    person4
person1    person5
person2    person1
person2    person3
person2    person4
person2    person5
person3    person1
person3    person2
person3    person4
person3    person5
person4    person1
person4    person2
person4    person3
person4    person5
person5    person1
person5    person2
person5    person3
person5    person4

但我正在想办法让它看起来像这样:

01-01    person1    person2
01-01    person1    person3
01-01    person1    person4
01-02    person1    person5
01-02    person2    person1
01-02    person2    person3
01-03    person2    person4
01-03    person2    person5
01-03    person3    person1
01-04    person3    person2
01-04    person3    person4
01-04    person3    person5
01-05    person4    person1
01-05    person4    person2
01-05    person4    person3
01-06    person4    person5
01-06    person5    person1
01-06    person5    person2
01-07    person5    person3
01-07    person5    person4

这是T-SQL我目前拥有的:

If Object_Id('TempDb..#namez') Is Not Null 
     Drop Table #namez

Create Table #namez
(
     namezId Int Not Null Primary Key,
     membername VarChar(48)
)

Insert Into #namez
Values (10 ,'person1'), (11 , 'person2'),
       (12 , 'person3'), (13 , 'person4'),
       (14 , 'person5')

If Object_Id('TempDb..#groups') Is Not Null 
     Drop Table #groups

Create Table #groups
(
    groupsId Int Not Null Primary Key,
    GroupCode Char(5)
)

Insert Into #groups
Values (10, '01-01'), (11, '01-02'), (12, '01-03'),
       (13, '01-04'), (14, '01-05'), (15, '01-06'), (16, '01-07')


Select 
    TeamOne.membername, TeamTwo.membername 
From    
    #namez TeamOne 
Full Outer Join 
    #namez TeamTwo On TeamOne.membername != TeamTwo.membername
order by 
    teamone.membername, teamtwo.membername

谢谢!

您可以使用CROSS JOIN

DB FIDDLE

Select     TeamOne.membername , TeamTwo.membername 
From       #namez TeamOne 
cross join #namez TeamTwo
where      TeamOne.membername != TeamTwo.membername 
order by   teamone.membername,teamtwo.membername

对现有内容进行一些调整。

我们使用 row_number() 根据我们需要如何拆分团队来对团队进行分组。然后使用它,加上 min() GroupId 加入组 table.

这假设组 table 中的 GroupId 是连续的,并且应该考虑或多或少的团队和或多或少的组。

试一试:

IF OBJECT_ID('TempDb..#namez') IS NOT NULL
    DROP TABLE [#namez];

CREATE TABLE [#namez]
    (
        [namezId] INT NOT NULL PRIMARY KEY
      , [membername] VARCHAR(48)
    );

INSERT INTO [#namez]
VALUES ( 10, 'person1' )
     , ( 11, 'person2' )
     , ( 12, 'person3' )
     , ( 13, 'person4' )
     , ( 14, 'person5' );

IF OBJECT_ID('TempDb..#groups') IS NOT NULL
    DROP TABLE [#groups];

CREATE TABLE [#groups]
    (
        [groupsId] INT NOT NULL PRIMARY KEY
      , [GroupCode] CHAR(5)
    );

INSERT INTO [#groups]
VALUES ( 10, '01-01' )
     , ( 11, '01-02' )
     , ( 12, '01-03' )
     , ( 13, '01-04' )
     , ( 14, '01-05' )
     , ( 15, '01-06' )
     , ( 16, '01-07' );


DECLARE @GroupComboCount INT
      , @GroupCount DECIMAL(12, 2)
      , @TeamCount DECIMAL(12, 2)
      , @MinGroupId INT;

--What is our group count
SET @GroupCount = (
                      SELECT COUNT(*)
                      FROM   [#groups]
                  );
--What is our team count
SET @TeamCount = (
                     SELECT          COUNT(*)
                     FROM            [#namez] [TeamOne]
                     FULL OUTER JOIN [#namez] [TeamTwo]
                         ON [TeamOne].[membername] != [TeamTwo].[membername]
                 );
--How should I uniformly split the teams 
SET @GroupComboCount = ROUND(@TeamCount / @GroupCount, 0);

--What is the min group so I can build my relationship back to groups.
SET @MinGroupId = (
                      SELECT MIN([groupsId])
                      FROM   [#groups]
                  );

SELECT   grp.*, [TeamGroups].*
FROM     (
             SELECT          ( ROW_NUMBER() OVER ( ORDER BY [TeamOne].[membername]
                                                          , [TeamTwo].[membername]
                                                 ) + ( @GroupComboCount - 1 )
                             ) / @GroupComboCount AS [TeamGrouping] --This does my group based on the @GroupComboCount
                           , [TeamOne].[membername] AS [Member1]
                           , [TeamTwo].[membername] AS [Member2]
             FROM            [#namez] [TeamOne]
             FULL OUTER JOIN [#namez] [TeamTwo]
                 ON [TeamOne].[membername] != [TeamTwo].[membername]
         ) AS [TeamGroups]
INNER JOIN [#groups] grp ON grp.[groupsId] = @MinGroupId+[TeamGroups].[TeamGrouping]-1 --Here we then relate that back to my groups.
ORDER BY [TeamGroups].[Member1]
       , [TeamGroups].[Member2];