解决方案
查询
SELECT a.introtext FROM ( SELECT b.content_item_id as id,COUNT(DISTINCT b.tag_id) as rc FROM `#__contentitem_tag_map` AS `b` INNER JOIN `#__tags` AS `c` ON (`b`.`tag_id` = `c`.`id`) WHERE `c`.`alias` IN ("") GROUP BY `b`.`content_item_id`)f INNER JOIN `#__content` AS `a` ON (`a`.`id` = `f`.`id`) INNER JOIN `#__contentitem_tag_map` AS `b` ON (`a`.`id` = `b`.`content_item_id`) INNER JOIN `#__tags` AS `c` ON (`b`.`tag_id` = `c`.`id`) WHERE `c`.`alias` IN ("") AND `a`.`state` = 1 AND `c`.`level` > 0 AND `c`.`published` = 1 AND `a`.`catid` = 27 AND `f`.`rc` = 1 GROUP BY `a`.`id` ORDER BY a.title ASC
Joomla SQL
这是自定义模块中的 Joomla SQL
// Create a new query object.
$subQuery = $db->getQuery(true);
$query = $db->getQuery(true);
$tags = array('facebook','html5');
$count = count($tags);
$tags = '"' . implode('","',$tags) . '"';
$subQuery
->select(array('b.content_item_id as id','COUNT(DISTINCT b.tag_id) as rc'))
->from($db->quoteName('#__contentitem_tag_map','b'))
->join('INNER', $db->quoteName('#__tags', 'c') . ' ON (' . $db->quoteName('b.tag_id') . ' = ' . $db->quoteName('c.id') . ')')
->where(($db->quoteName('c.alias') . ' IN ('.$tags.')'))
->group($db->quoteName('b.content_item_id'));
$query
->select(array('a.introtext'))
->from('('.$subQuery.')f')
->join('INNER', $db->quoteName('#__content', 'a') . ' ON (' . $db->quoteName('a.id') . ' = ' . $db->quoteName('f.id') . ')')
->join('INNER', $db->quoteName('#__contentitem_tag_map', 'b') . ' ON (' . $db->quoteName('a.id') . ' = ' . $db->quoteName('b.content_item_id') . ')')
->join('INNER', $db->quoteName('#__tags', 'c') . ' ON (' . $db->quoteName('b.tag_id') . ' = ' . $db->quoteName('c.id') . ')')
->where(($db->quoteName('c.alias') . ' IN ('.$tags.')'), 'AND')
->where(($db->quoteName('f.rc') . ' = ' . $count))
->group($db->quoteName('a.id'))
->order('a.title ASC');
我正在使用 MySQL 和 Joomla! 3.8 数据库.
正在使用的表
- #__内容
- #__contentitem_tag_map
- #__标签
故事
我创建了包含开发人员资料的文章。每个开发人员都可以用“jQuery”、“html5”等技能标记自己。 这些技能作为标签存储在#__tags 表中。
我尝试从#content 表中选择与我正在搜索的标签相匹配的所有开发人员。
例如,我正在寻找一名既能处理“HTML5”又能处理“JavaScript”的开发人员。
结果应该是空的,因为在我的数据库中只有一个针对“HTML5”和“CSS3”的开发和另一个针对“CSS3”的开发。
丑陋的真相
搜索“HTML5”和“Javascript”会返回 1 个结果。
它应该是这样的
搜索“HTML5”和“Javascript”应该返回 0 个结果,因为没有同时具备这两种技能的开发人员。
查询
SELECT
a.id as id,
a.title,
c.id as tag_id,
c.alias as tag_alias
FROM `#__content` as `a`
INNER JOIN `#__contentitem_tag_map` AS b ON (a.id = b.content_item_id)
INNER JOIN `#__tags` AS c ON (b.tag_id = c.id)
WHERE c.alias IN ('html5','javascript')
id | title | tag_id | tag_alias
-------------------------------
22 | xyz | 6 | html5
问题
要做什么?顺便说一句,我不能使用像 HAVING COUNT(\*) = x;
这样的东西,因为会有多个带有多个标签的结果。
感谢您的支持! <3
附加信息
使用 HAVING COUNT(\*) = x
(其中 x 是使用的标签数量)仅返回 1 个开发人员/标签,而不是每个具有此特定标签的开发人员。
SQL fiddle
最佳答案
我试图为您的问题找到解决方案(我不确定查询是否可以更好;我不太喜欢我必须重复两次条件 c.alias IN ('html5','javascript' )).
也许这对您来说并不重要,但此查询也可以用于 Mysql 以外的其他数据库引擎(例如 MSSQL),因为它不使用 GROUP_CONCAT 或“许可的”GROUP BY 子句。
查询似乎适用于除两个以外的更多值(例如,要检查的三个别名),当然也会更改 RC 的条件。
在内部,它计算表 #__contentitem_tag_map 中存在的每个标签的(不同)值:因此在外部,查询可以提取具有至少两个(或所需数量,在 WHERE 条件 RC= 中指定)的标签xx) 存在的值。这允许“模拟”您需要的那种“AND 条件”。在外部查询中进行其他必要的连接以提取所需的列。
(在内部,如您所见,没有必要使用表#__content)。
我在您的示例数据中添加了以下数据:
INSERT INTO `#__content` (`id`, `title`) VALUES (29, 'New one');
INSERT INTO `#__contentitem_tag_map` (`content_item_id`, `tag_id`) VALUES (29, 6);
INSERT INTO `#__contentitem_tag_map` (`content_item_id`, `tag_id`) VALUES (29, 1);
INSERT INTO `#__tags` (`id`, `alias`) VALUES (1,'facebook');
SELECT F.ID,
A.title as title,
B.tag_id,
C.alias as tag_alias
FROM (SELECT b.content_item_id as id,
COUNT(DISTINCT b.tag_id) AS RC
FROM `#__contentitem_tag_map` AS b
INNER JOIN `#__tags` AS c ON b.tag_id = c.id
WHERE c.alias IN ('html5','facebook')
GROUP BY b.content_item_id
) F
INNER JOIN `#__content` A ON A.id = F.id
INNER JOIN `#__contentitem_tag_map` B ON a.id = B.content_item_id
INNER JOIN `#__tags` C ON B.tag_id = C.id
WHERE C.alias IN ('html5','facebook')
AND F.RC=2;
;
输出:
ID title tag_id tag_alias
1 29 New one 6 html5
2 29 New one 1 facebook
关于MySQL:仅当 IN() 中的所有值都匹配结果时才返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46489064/