【发布时间】:2014-09-26 04:39:55
【问题描述】:
这是一个可以解释我的问题的简单测试数据库:
CREATE TABLE `articles` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`article_title` varchar(50) NOT NULL,
PRIMARY KEY (`article_id`)
);
INSERT INTO `articles` VALUES(1, 'first article');
INSERT INTO `articles` VALUES(2, 'second article');
CREATE TABLE `flags` (
`flag_id` int(11) NOT NULL AUTO_INCREMENT,
`flag_name` varchar(50) NOT NULL,
PRIMARY KEY (`flag_id`)
);
INSERT INTO `flags` VALUES(1, 'red');
INSERT INTO `flags` VALUES(2, 'blue');
INSERT INTO `flags` VALUES(3, 'green');
INSERT INTO `flags` VALUES(4, 'orange');
INSERT INTO `flags` VALUES(5, 'purple');
CREATE TABLE `map` (
`map_article_id` int(11) NOT NULL,
`map_flag_id` int(11) NOT NULL,
PRIMARY KEY (`map_article_id`,`map_flag_id`),
KEY `map_flag_id` (`map_flag_id`)
);
INSERT INTO `map` VALUES(1, 1);
INSERT INTO `map` VALUES(1, 2);
INSERT INTO `map` VALUES(2, 2);
INSERT INTO `map` VALUES(2, 3);
INSERT INTO `map` VALUES(1, 4);
原始:
article_id article_title
1 first article
2 second article
flag_id flag_name
1 red
2 blue
3 green
4 orange
5 purple
map_article_id map_flag_id
1 1
1 2
2 2
2 3
1 4
一个带有文章的表格,一个带有标志,一个带有映射文章标志。
选择所有带有联合标志的文章很容易,并且工作正常:
SELECT `article_id` , `article_title` , GROUP_CONCAT( `flag_name` )
FROM `articles`
LEFT JOIN `map` ON `map_article_id` = `article_id`
LEFT JOIN `flags` ON `flag_id` = `map_flag_id`
GROUP BY `article_id`
结果是:
article_id article_title GROUP_CONCAT(`flag_name`)
1 first article red,blue,orange
2 second article blue,green
问题是,我想找到所有带有某些指定标志但 GROUP_CONCAT 字段完好无损的文章。当我添加 WHERE map_flag_id = 1 查询返回:
article_id article_title GROUP_CONCAT(`flag_name`)
1 first article red
如何在最后一列中仅获取带有红色但所有红色,蓝色,橙色标志的文章?请不要建议“LIKE %red%”,我需要这个快。
谢谢
编辑
也许?
SELECT `article_id` , `article_title` , (
SELECT GROUP_CONCAT( `flag_name` )
FROM `flags`
LEFT JOIN `map` ON `map_flag_id` = `flag_id`
WHERE `map_article_id` = `article_id`
)
FROM `articles`
LEFT JOIN `map` ON `map_article_id` = `article_id`
LEFT JOIN `flags` ON `flag_id` = `map_flag_id`
WHERE `flag_id` =1
GROUP BY `article_id`
【问题讨论】:
-
LIKE在HAVING或HAVING FIND_IN_SET('red', flags)中应用时不一定会很慢,因为它们都是在聚合完成后应用的。性能是否足以满足您的需求?否则,在聚合之前您需要一个额外的内部连接(可能是 2 个),这会更慢。您建议的子选择可能比所有这些都慢。这取决于将返回多少个分组的 article_id。如果只是少数,HAVING FIND_IN_SET()将没有可衡量的差异。如果是数千,它会慢一点。 -
您编辑的解决方案似乎是有效的。或者,您可以使用带有此条件的原始查询
WHERE article_id IN (SELECT map_article_id FROM map WHERE map_flag_id=?)。或者,第二次加入map并满足条件。
标签: mysql join group-concat