如何使用一对多优雅地检索数据库数据?

时间:2011-09-20 01:17:34

标签: php mysql

我正在查询数据库以检索包含一对多关系的一些信息。考虑:

CREATE TABLE `movies` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(50) NOT NULL,
  `desc` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `movies` VALUES ('1', 'The Princess Bride', 'A fantastic film of epic adventure, action, and love.');


CREATE TABLE `showtimes` (
  `movie_id` int(10) unsigned NOT NULL,
  `showtime_id` int(10) unsigned NOT NULL auto_increment,
  `starttime` timestamp NOT NULL,
  PRIMARY KEY  (`movie_id`,`showtime_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `showtimes` VALUES ('1', '1', '2011-09-19 20:00:00'), ('1', '2', '2011-09-19 23:00:00'), ('1', '3', '2011-09-20 13:00:00');

我希望收到信息的方式是这样的。

$movies[1] = array(
    'id' => 1, 
    'title' => 'The Princess Bride', 
    'desc' => 'A fantastic film of epic adventure, action, and love.', 
    'showtimes' => array(
        '1' => '2011-09-19 20:00:00', 
        '2' => '2011-09-19 23:00:00', 
        '3' => '2011-09-20 13:00:00'));

这似乎是我查看数据最明智的方式。如果我打印剧院的所有放映时间,我可以做一些简单的事情:

foreach($movies as $movie)
{
    //pretend there's style stuff here
    echo $movie['title'] . "&mdash" . $movie['desc'];
    foreach($movie['showtime'] as $time)
    {
        if ($time > $_SERVER['REQUEST_TIME'])
        {
            echo $time;
        }
    }
}

不幸的是,这不是我从标准查询中得到的。类似的东西:

SELECT * FROM `movies` INNER JOIN `showtimes` ON `movies`.`id` = `showtimes`.`movie_id`;

收率:

$movies[1] = array('id' => 1, 'title' => 'The Princess Bride', 'desc' => 'A fantastic film of epic adventure, action, and love.', 'starttime' => '2011-09-19 20:00:00');
$movies[2] = array('id' => 1, 'title' => 'The Princess Bride', 'desc' => 'A fantastic film of epic adventure, action, and love.', 'starttime' => '2011-09-19 23:00:00');
$movies[3] = array('id' => 1, 'title' => 'The Princess Bride', 'desc' => 'A fantastic film of epic adventure, action, and love.', 'starttime' => '2011-09-20 13:00:00');

这不是我想要的。在具有更多数据的较大结果集中,我也对返回如此多的重复数据的效果感到有些好奇(考虑使用数十个连接的更宽行)。

我知道我可以使用像GROUP_CONCAT()之类的构造来将这些放映时间附加在一起,但是我稍后会将它们分开。对于像时间戳这样简单的事情,它很容易,因为我可以选择不会以该格式出现的分隔符,如果我分割评论,例如它会有点难度。

我可以做一些蹩脚的事情,例如遍历所有电影,从该循环中查询放映时间,但是没有办法将 web scale

我可以在查询中执行连接,然后迭代这些结果并附加重复的主键,但这似乎也缺乏优雅。

问题

是否有优雅的方式来获取我正在寻找的东西?在这个特定的应用程序中,我正在使用Zend Framework,如果它内置于那个非常敏锐的那个(或另一个框架)中。

感谢

1 个答案:

答案 0 :(得分:1)

在两个表上进行某种连接(您的选择),然后遍历结果。

$query = "SELECT * FROM movies LEFT JOIN showtimes ON showtimes.movie_id = movies.id";
$result = $db->query($query);
while($row = $result->fetch()){
  if(isset($movies[$row['id']])
    $movies[$row['id']]['showtimes'][] = $row['starttime'];
  else{
    $movies[$row['id']] = array(
      'id'=>$row['id'],
      'title'=>$row['title'],
      'desc'=>$row['desc'],
      'showtimes'=>array($row['starttime'])
    );
  }
}