Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用多对多关系优化mysql COUNT()查询(通过第三个表)_Mysql_Sql_Group By_Count_Many To Many - Fatal编程技术网

如何使用多对多关系优化mysql COUNT()查询(通过第三个表)

如何使用多对多关系优化mysql COUNT()查询(通过第三个表),mysql,sql,group-by,count,many-to-many,Mysql,Sql,Group By,Count,Many To Many,以下是我执行的查询: SELECT COUNT(*) FROM (SELECT `p`.* FROM `shop_products` `p` LEFT JOIN `shop_tag_assignments` ON `p`.`id` = `shop_tag_assignments`.`product_id` LEFT JOIN `shop_tags` ON `shop_tag_assignments

以下是我执行的查询:

SELECT COUNT(*)
FROM (SELECT `p`.*
      FROM `shop_products` `p` LEFT JOIN
           `shop_tag_assignments`
           ON `p`.`id` = `shop_tag_assignments`.`product_id` LEFT JOIN
           `shop_tags`
           ON `shop_tag_assignments`.`tag_id` = `shop_tags`.`id`
      WHERE `p`.`status`=1
      GROUP BY `p`.`id`
     ) `c`

这个查询大约需要300毫秒(我觉得太长了…)

解释问题:

数据库表转储:

车间标签中的1k记录

CREATE TABLE `shop_tags` (
  `id` int(11) NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `label` text COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ALTER TABLE `shop_tags`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `idx-shop_tags-slug` (`slug`),
  ADD KEY `id` (`id`);

ALTER TABLE `shop_tags`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1162;
COMMIT;

CREATE TABLE `shop_tag_assignments` (
  `product_id` int(11) NOT NULL,
  `tag_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `shop_tag_assignments`
  ADD PRIMARY KEY (`product_id`,`tag_id`),
  ADD KEY `idx-shop_tag_assignments-product_id` (`product_id`),
  ADD KEY `idx-shop_tag_assignments-tag_id` (`tag_id`),
  ADD KEY `_index_name` (`product_id`,`tag_id`),
  ADD KEY `__index_name` (`tag_id`,`product_id`);

ALTER TABLE `shop_tag_assignments`
  ADD CONSTRAINT `fk-shop_tag_assignments-product_id` FOREIGN KEY (`product_id`) REFERENCES `shop_products` (`id`) ON DELETE CASCADE,
  ADD CONSTRAINT `fk-shop_tag_assignments-tag_id` FOREIGN KEY (`tag_id`) REFERENCES `shop_tags` (`id`) ON DELETE CASCADE;
COMMIT;

车间标签分配的表结构

车间标签作业中的224k条记录

CREATE TABLE `shop_tags` (
  `id` int(11) NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `label` text COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ALTER TABLE `shop_tags`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `idx-shop_tags-slug` (`slug`),
  ADD KEY `id` (`id`);

ALTER TABLE `shop_tags`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1162;
COMMIT;

CREATE TABLE `shop_tag_assignments` (
  `product_id` int(11) NOT NULL,
  `tag_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `shop_tag_assignments`
  ADD PRIMARY KEY (`product_id`,`tag_id`),
  ADD KEY `idx-shop_tag_assignments-product_id` (`product_id`),
  ADD KEY `idx-shop_tag_assignments-tag_id` (`tag_id`),
  ADD KEY `_index_name` (`product_id`,`tag_id`),
  ADD KEY `__index_name` (`tag_id`,`product_id`);

ALTER TABLE `shop_tag_assignments`
  ADD CONSTRAINT `fk-shop_tag_assignments-product_id` FOREIGN KEY (`product_id`) REFERENCES `shop_products` (`id`) ON DELETE CASCADE,
  ADD CONSTRAINT `fk-shop_tag_assignments-tag_id` FOREIGN KEY (`tag_id`) REFERENCES `shop_tags` (`id`) ON DELETE CASCADE;
COMMIT;

Mysql版本
5.7.16-10-log

删除子查询。而且不要经常使用反勾号:

SELECT COUNT(DISTINCT p.id)
FROM shop_products p LEFT JOIN
     shop_tag_assignments sta
     ON p.id = sta.product_id LEFT JOIN
     shop_tags st
     ON sta.tag_id = st.id
WHERE p.status = 1;
对于此查询,您需要有关
shop\u产品(状态,id)
的索引

接下来,您的查询将计算内部子查询通过
p.id
聚合后返回的行数。您使用的是
左联接
,因此未筛选出任何内容。这意味着连接实际上是冗余的。我认为这也是同样的道理:

SELECT COUNT(*)
FROM shop_products p 
WHERE p.status = 1;

这应该比你的版本快得多。但是,您的版本非常快,因此您可能不会注意到有太大的差异。

此查询中需要“LEFT JOIN”,因为我想按产品的标记名筛选产品。很抱歉没有事先澄清这一点。也许还有另一种方法可以计算产品的数量,并分别按标签名称进行过滤?这不是这个问题所问的问题,但您可以在第一次查询中使用
where