帮助SELECT语句

时间:2010-01-03 17:42:26

标签: sql mysql join

我有两张桌子:球员和牌2

在每个cards2行中,至少有一个玩家ID(pid,pid2,pid3,pid4)。我试图提出一个select语句来获取所有fname和lname,如果有多个玩家ID(pid不是0)。总有一个pid,但并不总是pid2,pid3等。这有意义吗?

以下是结构。

玩家表

CREATE TABLE IF NOT EXISTS `players` (
  `player_id` mediumint(10) NOT NULL AUTO_INCREMENT,
  `sport_id` tinyint(4) NOT NULL,
  `fname` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `lname` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `hof` tinyint(4) NOT NULL,
  PRIMARY KEY (`player_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=421 ;

Cards2表

CREATE TABLE IF NOT EXISTS `cards2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pid` mediumint(10) NOT NULL,
  `pid2` mediumint(10) NOT NULL,
  `pid3` mediumint(10) NOT NULL,
  `pid4` mediumint(10) NOT NULL,
  `num` smallint(4) NOT NULL DEFAULT '0',
  `year` year(4) NOT NULL DEFAULT '0000',
  `notes` text,
  `new_manuf` varchar(50) NOT NULL,
  `sportid` tinyint(4) NOT NULL DEFAULT '0',
  `fname` varchar(25) NOT NULL,
  `lname` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=572 ;

提前致谢!

4 个答案:

答案 0 :(得分:3)

你可以这样做:

SELECT
    id,
    P1.fname AS fname1,
    P1.lname AS lname1,
    P2.fname AS fname2,
    P2.lname AS lname2,
    P3.fname AS fname3,
    P3.lname AS lname3,
    P4.fname AS fname4,
    P4.lname AS lname4
FROM cards2
LEFT JOIN players P1 ON pid = P1.player_id
LEFT JOIN players P2 ON pid2 = P2.player_id
LEFT JOIN players P3 ON pid3 = P3.player_id
LEFT JOIN players P4 ON pid4 = P4.player_id

您可能想要考虑normalize your database是否是个好主意。四个玩家有四列似乎是一个坏主意。如果你以后想要允许6名玩家怎么办?

答案 1 :(得分:3)

如果有可能,您可能需要考虑重新设计表格。 CARD2表中的重复玩家ID将使查询变得困难并且人为地限制可以与特定卡相关联的玩家数量。如果你还处于设计阶段,你现在可以通过重做现在来节省一些自己的悲伤。这是一个快速的镜头:

首先,重做'cards2'表以消除玩家参考:

CREATE TABLE IF NOT EXISTS `cards2` ( 
  `card_id` int(11) NOT NULL AUTO_INCREMENT, 
  `num` smallint(4) NOT NULL DEFAULT '0', 
  `year` year(4) NOT NULL DEFAULT '0000', 
  `notes` text, 
  `new_manuf` varchar(50) NOT NULL, 
  `sportid` tinyint(4) NOT NULL DEFAULT '0', 
  PRIMARY KEY (`card_id`) 
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=572;

然后创建所谓的“联结表”来映射卡和玩家之间的多对多关系(即一个玩家可以出现在许多牌上,并且许多玩家可以出现在一张牌上):

CREATE TABLE IF NOT EXISTS 'card_player' (
  'card_id' int(11) NOT NULL,
  'player_id' mediumint(10) NOT NULL,
  PRIMARY KEY ('card_id', 'player_id'),
  FOREIGN KEY 'card_id' REFERENCES card2.card_id,
  FOREIGN KEY player_id REFERENCES players.player_id
) ENGINE=MYISAM  DEFAULT CHARSET=latin1;

消除CARDS2表中重复的player_id应该使查询更容易。例如,

SELECT c.card_id, p.fname, p.lname
  FROM players p,
       cards2 c,
       card_player x
  WHERE x.card_id = c.card_id AND
        p.player_id = x.player_id
  ORDER BY c.card_id;

这也消除了最多只有四名玩家与特定牌相关联的限制,所以如果你有一张有20名玩家的团队卡,这套新的表定义可以处理它。

我希望这会有所帮助。

答案 2 :(得分:1)

使用:

   SELECT CONCAT(p1.fname, ' ', p1.lname) AS player1,
          CONCAT(p2.fname, ' ', p2.lname) AS player2,
          CONCAT(p3.fname, ' ', p3.lname) AS player3,
          CONCAT(p4.fname, ' ', p4.lname) AS player4,
     FROM CARDS2 c
     JOIN PLAYERS p1 ON p1.playerid = c.pid
LEFT JOIN PLAYERS p2 ON p2.playerid = c.pid2
LEFT JOIN PLAYERS p3 ON p3.playerid = c.pid3
LEFT JOIN PLAYERS p4 ON p4.playerid = c.pid4

答案 3 :(得分:1)

关于理解,创建简单的n:m players_tables_map表不是更清晰吗? http://en.wikipedia.org/wiki/First_normal_form