我有一个名为users的表,我有id auto auto inc主键,用户名,密码,电子邮件,admin_level
我想循环每个用户名并将它们插入名为matchups的新表
牌桌比赛有tournament_id,player_1,player_2。我需要从上一个表中拆分每个用户名,并为每个用户名分配player_1和player_2
最终结果是在注册时让玩家与玩家对战
答案 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
非常感谢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
。