【问题标题】:how to have a select query that generates host-guests table planed games?如何有一个选择查询来生成主客桌游戏?
【发布时间】:2015-09-23 13:33:29
【问题描述】:

我有一张桌子,上面有 16 个足球队的名字:

ID  Team Name
..  ..
8   MANUTD
..  
13  CHELSEA
..  ..

如何通过选择查询获得第二个表,该查询会为赛季中的每一周生成随机比赛?每支球队与其他球队比赛两次,第一次作为东道主,第二次作为客人,显然每支球队每周比赛一次。两支球队在半个赛季中从未有过两次交手,下一次他们在第二个赛季的比赛中,他们在两个领域的位置将随着主阵风顺序而改变。我怎么会有这样的选择查询?

表 2 - 上半赛季的比赛

ID  Host    Guest   Result
..  ..  ..  ..      ..
..  MANUTD  CHELSEA ..

表 2 - 第二个半赛季的比赛

..  ..  ..  ..
..  CHELSEA MANUTD  ..
..  ..  ..  ..

【问题讨论】:

  • 您应该考虑在sqlfiddle.com 中创建表格以鼓励更多回复
  • 您使用的是哪个 DBMS?后格雷斯?甲骨文?

标签: sql select


【解决方案1】:

到目前为止,我开发了一个单周日历的创建。明天我将添加完整日历的循环:

DECLARE @CTR INT
DECLARE @HOST INT
DECLARE @GUEST INT
DECLARE @TEAMS TABLE (Ind INT, Name VARCHAR(50))
DECLARE @MATCHES TABLE (Ind INT, Host INT, Guest INT)

INSERT  @TEAMS (Ind, Name) VALUES ( 1, 'Arsenal')
INSERT  @TEAMS (Ind, Name) VALUES ( 2, 'Aston Villa')
INSERT  @TEAMS (Ind, Name) VALUES ( 3, 'Bournemouth')
INSERT  @TEAMS (Ind, Name) VALUES ( 4, 'Chelsea')
INSERT  @TEAMS (Ind, Name) VALUES ( 5, 'Crystal Palace')
INSERT  @TEAMS (Ind, Name) VALUES ( 6, 'Everton')
INSERT  @TEAMS (Ind, Name) VALUES ( 7, 'Leicester')
INSERT  @TEAMS (Ind, Name) VALUES ( 8, 'Liverpool')
INSERT  @TEAMS (Ind, Name) VALUES ( 9, 'Manchester City')
INSERT  @TEAMS (Ind, Name) VALUES (10, 'Manchester Utd')
INSERT  @TEAMS (Ind, Name) VALUES (11, 'Newcastle')
INSERT  @TEAMS (Ind, Name) VALUES (12, 'Norwich City')
INSERT  @TEAMS (Ind, Name) VALUES (13, 'Southampton')
INSERT  @TEAMS (Ind, Name) VALUES (14, 'Stoke City')
INSERT  @TEAMS (Ind, Name) VALUES (15, 'Sunderland')
INSERT  @TEAMS (Ind, Name) VALUES (16, 'Swansea City')
INSERT  @TEAMS (Ind, Name) VALUES (17, 'Tottenham')
INSERT  @TEAMS (Ind, Name) VALUES (18, 'Watford')
INSERT  @TEAMS (Ind, Name) VALUES (19, 'West Bromwich')
INSERT  @TEAMS (Ind, Name) VALUES (20, 'West Ham') 

SET @CTR = 0 

WHILE 1 = 1 BEGIN
   SET @CTR = @CTR + 1
   SET @HOST = 0
   SET @GUEST = 0
   WHILE 1 = 1 BEGIN
      SET @HOST  = FLOOR(RAND() * 20) + 1
      SET @GUEST = FLOOR(RAND() * 20) + 1
      IF NOT EXISTS(SELECT Host  From @MATCHES WHERE Host  = @HOST ) AND
         NOT EXISTS(SELECT Host  From @MATCHES WHERE Host  = @GUEST) AND
         NOT EXISTS(SELECT Guest From @MATCHES WHERE Guest = @HOST ) AND
         NOT EXISTS(SELECT Guest From @MATCHES WHERE Guest = @GUEST) AND
         @HOST <> @GUEST BREAK
   END
   INSERT @MATCHES (Ind, Host, Guest) VALUES ( 1, @HOST, @GUEST)
   IF @CTR = 10 BREAK
END

SELECT A.Ind, B.Name, C.Name FROM @MATCHES A
JOIN @TEAMS B ON Host = B.Ind
JOIN @TEAMS C ON Guest = C.Ind

【讨论】:

    【解决方案2】:

    因为这使用了一些循环和表变量,所以对于大型集合来说,它不是最有效的解决方案。但是,如果您只对 16 个团队执行一次此操作,则可以:

    create table Teams (team varchar(5))
    insert into Teams(team) values
    ('a'),
    ('b'),
    ('c'),
    ('d'),
    ('e'),
    ('f'),
    ('g'),
    ('h'),
    ('i'),
    ('j'),
    ('k'),
    ('l'),
    ('m'),
    ('n'),
    ('o'),
    ('p')
    

    使用独占交叉连接来创建独特的对决:

    declare @Matchups table (home varchar(5), away varchar(5), orderNo float)
    insert into @Matchups
    select * from (
    select x1.team as home, x2.team as away,RAND(CHECKSUM(NEWID())) as orderNo from @x x1
    cross join @x x2
    where x1.tm <> x2.tm
    ) a
    
    declare @half1 table (home varchar(5), away varchar(5), week int)
    declare @matchup int = 15
    declare @week int = 15
    

    创建第一场比赛,然后在表格中循环,确保没有球队在同一周比赛两次并且没有重复比赛

    delete top(1) from @Matchups
    output deleted.home,deleted.away,@week into @half1
    
    set @matchup = @matchup - 1
    
    while @week > 0
    begin
        while @matchup > 0
        begin
            delete top(1) s
            output deleted.home,deleted.away,@week into @half1
            from @Matchups s
            where not exists (
                        select 1 from @half1 m
                        where ((m.away = s.away
                        or m.away = s.home 
                        or m.home = s.away
                        or m.home = s.home)
                        and week = @week)
                        or
                        (m.away = s.away
                        and m.home = s.home)
                        or
                        (m.away = s.home
                        and m.home = s.away)
                        )
            set @matchup = @matchup - 1
        end
        set @week = @week - 1
        set @matchup = 15
    end
    
    set @week = 15
    set @matchup = 8
    

    对于下半场,只需以相反的主客场顺序将值插入表中,然后随机化比赛。

    declare @half2 table (home varchar(5), away varchar(5), week int)
    while @week > 0
    begin
        while @matchup > 0
        begin 
            insert into @half2
            select top 1 away,home,@week from 
            (select *,RAND(CHECKSUM(NEWID())) as orderNo from @half1 h1
            where not exists (
                            select 1 from @half2 h2
                            where (h1.away = h2.away 
                            or h1.away = h2.home 
                            or h1.home = h2.away 
                            or h1.home = h2.home)
                            and week = @week)) a
            order by orderNo
            set @matchup = @matchup - 1
        end
        set @matchup = 8
        set @week = @week - 1
    end
    
    
    select *,1 as Half from @half1
    union all
    select *,2 as Half from @half2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 2014-10-22
      • 2020-11-20
      • 2021-12-27
      • 1970-01-01
      相关资源
      最近更新 更多