在每行中获取Column username并将每个用户名分成player_1 Player_2

时间:2011-06-02 04:15:43

标签: php mysql

我有一个名为users的表,我有id auto auto inc主键,用户名,密码,电子邮件,admin_level

我想循环每个用户名并将它们插入名为matchups的新表

牌桌比赛有tournament_id,player_1,player_2。我需要从上一个表中拆分每个用户名,并为每个用户名分配player_1和player_2

最终结果是在注册时让玩家与玩家对战

1 个答案:

答案 0 :(得分:0)

好的......通常情况下,将数据从一个SQL表传输到另一个SQL表最好在SQL语言本身内完成,所以让我们看看我们如何做到这一点(我之前从未处理过这样的问题,所以我正在学习。)

我的测试表players,作为参考,是:

`player_id` `name`
1           Robert Doe
2           John Smith

制作所有可能的玩家排列

首先,试图找到两个球员的潜在排列。

我发现了一个类似的SO问题,但处理了两个表相互作用。 MySQL - Show All Permutations?。 MySQL可以在同一个查询中使用一个表两次,我们只需要为每个表设置别名,这样它们就不会发生冲突。

SELECT `p1`.`player_id` , `p1`.`name` , `p2`.`player_id` , `p2`.`name`
FROM `players` AS `p1`
CROSS JOIN `players` AS `p2`

这产生了以下结果:

`p1`.`player_id` `p1`.`name` `p2`.`player_id` `p2`.`name`
1                Robert Doe  1                Robert Doe
1                Robert Doe  2                John Smith
2                John Smith  1                Robert Doe
2                John Smith  2                John Smith

好的......除非人们在与自己对抗,否则就行不通,所以我们最好消除双方都相同的行。

注意:请跳至" 消除自我匹配&重复,但反转,匹配 - 修订后的解决方案"以获得更高效的以下步骤版本。 (旧的解决方案留在这里通过这个问题展示我自己的学习。

消除自我匹配

SELECT `p1`.`player_id` , `p1`.`name` , `p2`.`player_id` , `p2`.`name`
FROM `players` AS `p1`
CROSS JOIN `players` AS `p2`
WHERE `p1`.`player_id`!=`p2`.`player_id`

这产生了以下结果:

`p1`.`player_id` `p1`.`name` `p2`.`player_id` `p2`.`name`
1                Robert Doe  2                John Smith
2                John Smith  1                Robert Doe

好多了。现在,这很好,如果每个球员/球队互相比赛两次(例如,如果他们有一个主场和一场客场比赛),这是完美的,但如果这些是一对一的比赛,我们需要弄清楚如何过滤掉重复的匹配。

消除重复,但反转,匹配

每个成员都有一个身份证号码,数字,即好,数字,可以很容易地相互比较和排序。为了进行比较和排序,在每行的基础上,我们需要使用CASE条件。 (SQL MAX of multiple columns?

SELECT `p1`.`player_id` , `p1`.`name` , `p2`.`player_id` , `p2`.`name` ,
       CASE WHEN `p1`.`player_id`<`p2`.`player_id`
         THEN CONCAT( `p1`.`player_id` , '|' , `p2`.`player_id` )
         ELSE CONCAT( `p2`.`player_id` , '|' , `p1`.`player_id` )
       END AS `uniqueMatch`
FROM `players` AS `p1`
CROSS JOIN `players` AS `p2`
WHERE `p1`.`player_id`!=`p2`.`player_id`

返回

`p1`.`player_id` `p1`.`name` `p2`.`player_id` `p2`.`name` `uniqueMatch`
2                John Smith  1                Robert Doe 1|2
1                Robert Doe  2                John Smith 1|2

现在我们必须按照这些匹配对行进行分组

SELECT `p1`.`player_id` , `p1`.`name` , `p2`.`player_id` , `p2`.`name` ,
       CASE WHEN `p1`.`player_id`<`p2`.`player_id`
         THEN CONCAT( `p1`.`player_id` , '|' , `p2`.`player_id` )
         ELSE CONCAT( `p2`.`player_id` , '|' , `p1`.`player_id` )
       END AS `uniqueMatch`
FROM `players` AS `p1`
CROSS JOIN `players` AS `p2`
WHERE `p1`.`player_id`!=`p2`.`player_id`
GROUP BY `uniqueMatch`

返回:

`p1`.`player_id` `p1`.`name` `p2`.`player_id` `p2`.`name` `uniqueMatch`
2                John Smith  1                Robert Doe 1|2

在表格中添加另一行来检查它的行为:

`p1`.`player_id` `p1`.`name`  `p2`.`player_id` `p2`.`name` `uniqueMatch`
2                Robert Doe   1                John Smith  1|2
3                Matt Citizen 1                John Smith  1|3
3                Matt Citizen 2                Robert Doe  2|3

消除自我匹配&amp;重复,但反转,匹配 - 修订后的解决方案

非常感谢David Winant,解决方案可能会有所缩短。我们可以对CASE THEN CONCAT( ... ) ELSE ...子句应用简单的附加检查,而不是使用WHERE,以确保我们只获得一组匹配的玩家。同样,正如我们所知,玩家的ID将是不同的,因此一个将比另一个更大,我们可以检查是否可以消除一半返回的行。

SELECT `p1`.`player_id` , `p1`.`name` , `p2`.`player_id` , `p2`.`name`
FROM `players` AS `p1`
CROSS JOIN `players` AS `p2`
WHERE `p1`.`player_id`<`p2`.`player_id`

返回

`p1`.`player_id` `p1`.`name`  `p2`.`player_id` `p2`.`name`
1                John Smith   2                Robert Doe
1                John Smith   3                Matt Citizen
2                Robert Doe   3                Matt Citizen

再次感谢David Winant确认此修正案并与我分享 - 现在我已经学会了更多帮助解决这个问题。

出色!现在,我们可以使用这些结果自动插入另一个表:

将结果插入另一个表

如果我们手动执行此操作,我们会使用以下内容:

INSERT INTO `matches` ( `id_player1` , `id_player2` ) VALUES ( 2 , 1 ) , ( 3 , 1 ) ...

但是,我们可以使用上面的SELECT查询来处理所有VALUES位:

INSERT INTO `matches`
  ( `id_player1` , `id_player2` )
  SELECT `p1`.`player_id` , `p2`.`player_id`
  FROM `players` AS `p1`
  CROSS JOIN `players` AS `p2`
  WHERE `p1`.`player_id`<`p2`.`player_id`

产生表格:

`id_match` `id_player1` `id_player2`
1          2            1
2          3            1
3          3            2

而且,瞧,你拥有它!

新玩家的增量增加

以上是根据已建立的玩家表格(在每个人都在截止日期之前注册并且然后计算比赛的情况下很好),但是对于之后添加新用户/玩家的情况,可以使用以下代码添加新的匹配。

INSERT INTO `matches` ( `id_player1` , `id_player2` )
  SELECT 123 , `player_id`
  FROM `players`
  WHERE `player_id`!=123

其中123是新添加的播放器的player_id