MySQL: Return 仅当 IN() 中的所有值都匹配一个结果时
MySQL: Return only if all values in IN() match a result
解决方案
查询
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 数据库.
正在使用的表
- #__content
- #__contentitem_tag_map
- #__tags
故事
我创建了包含开发人员资料的文章。每个开发人员都可以使用 "jQuery"、"html5" 等技能标记 him/herself。
这些技能作为标签存储在#__tags table.
我尝试 select #content table 中与我正在搜索的标签相匹配的所有开发人员。
例如,我正在寻找一个可以 'HTML5' 和 'JavaScript' 的开发人员。
结果应该是空的,因为在我的数据库中只有 'HTML5' & 'CSS3' 的一个开发者和 'CSS3' 的另一个开发者。
丑陋的真相
正在搜索 'HTML5' 和 'Javascript' return 1 个结果。
应该的样子
搜索 'HTML5' 和 'Javascript' 应该 return 0 个结果,因为没有同时具备这两种技能的 Dev。
查询
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 是使用的标签数量)return仅 1 Developer/Tag 而不是每个开发人员都使用此特定标签。
SQL Fiddle
我试图为您的问题找到解决方案(我不确定查询是否可以更好;我不太喜欢我必须重复两次条件 c.alias IN ('html5','javascript')).
也许这对你来说并不重要,但是除了 Mysql(例如 MSSQL)之外,这个查询也可以用在其他数据库引擎上,因为它不使用 GROUP_CONCAT 或 "permissive" GROUP BY 子句。
查询似乎适用于除两个以外的更多值(例如要检查的三个别名),当然也更改 RC 的条件。
在内部,它计算 table 中每个标签的(不同的)值 #__contentitem_tag_map:所以在外部,查询可以提取至少有两个(或所需的数量,在 WHERE 条件 RC=xx) 中指定的值存在。这允许 "simulate" 您需要的 "AND condition" 类型。在外部查询中进行其他必要的连接以提取所需的列。
(在内部,如您所见,没有必要使用 table #__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
解决方案
查询
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 数据库.
正在使用的表
- #__content
- #__contentitem_tag_map
- #__tags
故事
我创建了包含开发人员资料的文章。每个开发人员都可以使用 "jQuery"、"html5" 等技能标记 him/herself。 这些技能作为标签存储在#__tags table.
我尝试 select #content table 中与我正在搜索的标签相匹配的所有开发人员。
例如,我正在寻找一个可以 'HTML5' 和 'JavaScript' 的开发人员。
结果应该是空的,因为在我的数据库中只有 'HTML5' & 'CSS3' 的一个开发者和 'CSS3' 的另一个开发者。
丑陋的真相
正在搜索 'HTML5' 和 'Javascript' return 1 个结果。
应该的样子
搜索 'HTML5' 和 'Javascript' 应该 return 0 个结果,因为没有同时具备这两种技能的 Dev。
查询
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 是使用的标签数量)return仅 1 Developer/Tag 而不是每个开发人员都使用此特定标签。
SQL Fiddle
我试图为您的问题找到解决方案(我不确定查询是否可以更好;我不太喜欢我必须重复两次条件 c.alias IN ('html5','javascript')).
也许这对你来说并不重要,但是除了 Mysql(例如 MSSQL)之外,这个查询也可以用在其他数据库引擎上,因为它不使用 GROUP_CONCAT 或 "permissive" GROUP BY 子句。
查询似乎适用于除两个以外的更多值(例如要检查的三个别名),当然也更改 RC 的条件。
在内部,它计算 table 中每个标签的(不同的)值 #__contentitem_tag_map:所以在外部,查询可以提取至少有两个(或所需的数量,在 WHERE 条件 RC=xx) 中指定的值存在。这允许 "simulate" 您需要的 "AND condition" 类型。在外部查询中进行其他必要的连接以提取所需的列。
(在内部,如您所见,没有必要使用 table #__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