具有外部表分组的T-SQL自联接表

时间:2018-11-30 17:01:01

标签: sql-server tsql group-by rollup

所需结果将是基于第二组的第一组分组。有一组应该与其他人匹配的人,以“房间”隔开,因此每个房间都统一使用。因此,如果有5个人和7个房间,则有20种组合,因此每个房间的使用次数不得超过3次(切线:每个房间都按顺序使用,因此不会有一个人同时出现在一个地方的危险)。每个分组有3对,但是随着增加的组行,每个组的对数应该减少;如果删除了其他组行,则每组对数应增加。如果我不在集合中思考,那感觉就像是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

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用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

答案 1 :(得分:1)

对您的内容进行一些调整。

我们使用row_number()根据需要的方式将团队分组。然后使用它,再加上min()GroupId来重新加入groups表。

这假设groups表中的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];