MYSQL,1:n与限制的单行关系

时间:2014-08-04 23:00:17

标签: php mysql relational-database

我有那些MySQL(简化)模式:

CREATE TABLE `library` (
  `id` varchar(32) NOT NULL,
  `app` varchar(32) NOT NULL,
  `filename` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `app` (`app`,`filename`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `tags` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `app` varchar(32) DEFAULT NULL,
  `tag` varchar(55) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `app` (`app`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

CREATE TABLE `library_tags` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `file` varchar(32) DEFAULT NULL,
  `tag` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8;

我的目标是为每个“标签”获取每个“库”条目。如果没有标签与库条目相关联,则它会在标签的字段中返回NULL。

这样做可以做到:

SELECT SQL_CALC_FOUND_ROWS library.*,
  GROUP_CONCAT( tags.`id` ORDER BY tags.`id` ASC SEPARATOR ',' ) as `tag_id`,
  GROUP_CONCAT( tags.`tag` ORDER BY tags.`id` ASC SEPARATOR ',' ) as `tag_name`
FROM `library` AS library
LEFT JOIN `library_tags` AS libtags
  ON library.`id` = libtags.`file` 
LEFT JOIN `tags` AS tags
  ON libtags.`tag` = tags.`id` 
WHERE library.`app` = "53bd8997ad2ee"
GROUP BY library.`id` 
ORDER BY  library.`created` DESC
LIMIT 99999 OFFSET 0 

我的下一步是添加一个限制,根据标签的id返回库的条目,如下所示:

SELECT SQL_CALC_FOUND_ROWS library.*,
  GROUP_CONCAT( tags.`id` ORDER BY tags.`id` ASC SEPARATOR ',' ) as `tag_id`,
  GROUP_CONCAT( tags.`tag` ORDER BY tags.`id` ASC SEPARATOR ',' ) as `tag_name`
FROM `library` AS library
LEFT JOIN `library_tags` AS libtags
  ON library.`id` = libtags.`file` 
LEFT JOIN `tags` AS tags
  ON libtags.`tag` = tags.`id` 
WHERE library.`app` = "53bd8997ad2ee"
  AND  tags.`id` IN (9,14) 
GROUP BY library.`id` 
ORDER BY  library.`created` DESC
LIMIT 99999 OFFSET 0 

也可以,但GROUP_CONCAT受限制影响,每个条目只返回选定的标签,而不是每个条目的完整标签列表。

我的问题是“如何使用每个条目的完整标记列表保留此单个查询?”

其他问题是:“这会影响MySQL的性能吗?”

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

将库标签限制放在LEFT JOIN条件中..

SELECT SQL_CALC_FOUND_ROWS library.*,
  GROUP_CONCAT( tags.`id` ORDER BY tags.`id` ASC SEPARATOR ',' ) as `tag_id`,
  GROUP_CONCAT( tags.`tag` ORDER BY tags.`id` ASC SEPARATOR ',' ) as `tag_name`
FROM `library` AS library
LEFT JOIN `library_tags` AS libtags
ON library.`id` = libtags.`file` 
LEFT JOIN `tags` AS tags
ON libtags.`tag` = tags.`id` 
AND tags.`id` IN (9,14) 
WHERE library.`app` = "53bd8997ad2ee"
GROUP BY library.`id` 
ORDER BY  library.`created` DESC
LIMIT 99999 OFFSET 0 

这会过滤附加的标签,而不是LEFT JOIN完成后返回的行。它应该以与第一次查询相同的速度运行,如果不是更快的话。