我使用phpMyAdmin提交查询。在子查询中使用GROUP BY时,整个应用程序只会挂起而没有错误,直到我重新启动浏览器。
我有三个表:files
存储有关上传文件的信息,file_category
定义文件的可用类别,file_category_r
存储文件和类别之间的关系。
我想计算每个类别有多少个文件,但有些文件可以在files表中有多个条目,所以我需要按files.filename
对它们进行分组。
我尝试了两种不同的方法,都导致了一个问题:
SELECT
fc.*,
(SELECT COUNT(*) FROM file_category_r
WHERE file_category_r.category_id = fc.id
AND file_category_r.file_id IN
(SELECT f2.id FROM
(SELECT * FROM files f3 GROUP BY f3.filename) f2
WHERE f2.mandant_id = 1)
) as file_count
FROM file_category fc ORDER BY name ASC
或
SELECT
fc.*,
(SELECT COUNT(*) FROM file_category_r
WHERE file_category_r.category_id = fc.id
AND file_category_r.file_id IN
(SELECT id FROM files WHERE mandant_id = 1 GROUP BY filename)
) as file_count
FROM file_category fc ORDER BY name ASC
我没有看到我的查询有问题,单独运行子查询就可以了。即使删除GROUP BY也会返回结果,但结果是错误的,因为它计算重复值。
以下是表架构:
CREATE TABLE IF NOT EXISTS `files` (
`id` bigint(20) unsigned NOT NULL,
`project_id` bigint(20) unsigned DEFAULT NULL,
`customer_id` bigint(20) unsigned DEFAULT NULL,
`opportunity_id` int(11) DEFAULT NULL,
`task_id` bigint(20) unsigned DEFAULT NULL,
`calendar_event_id` bigint(20) unsigned DEFAULT NULL,
`mandant_id` tinyint(4) DEFAULT NULL,
`time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`size` float NOT NULL,
`mime_type` varchar(100) NOT NULL,
`filename` text NOT NULL,
`file` longblob NOT NULL,
`folder_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`is_public` tinyint(1) unsigned NOT NULL DEFAULT '0',
`description` text,
`file_link` varchar(500) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=104832 ;
CREATE TABLE IF NOT EXISTS `file_category` (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`parent` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=445 ;
CREATE TABLE IF NOT EXISTS `file_category_r` (
`id` bigint(20) unsigned NOT NULL,
`file_id` bigint(20) unsigned NOT NULL,
`category_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=300346 ;
我做错了什么?表非常大,请求是否可能太重?我没有想法,请帮忙!谢谢!
答案 0 :(得分:1)
select fc.name, count(*)
from file_category fc
inner join file_category_r fcr on fc.id = fcr.category_id
group by fc.name
不太确定"有些文件可以在files表中有多个条目,所以我需要按files.filename"对它们进行分组。 也许你需要像
这样的东西select fc.name, count(distinct f.filename)
from file_category fc
inner join file_category_r fcr on fc.id = fcr.category_id
inner join files f on fcr.file_id = f.id
group by fc.name
答案 1 :(得分:0)
通常,使用in
会导致查询计划效率低下。您可以尝试使用exists
:
SELECT fc.*,
(SELECT COUNT(*)
FROM file_category_r fcr
WHERE fcr.category_id = fc.id AND
exists (select 1 from files f where f.mandant_id = 1 and fcr.file_id = f.id)
) as file_count
FROM file_category fc
ORDER BY name ASC;
现在,您应该添加索引。从file_category_r(category_id, file_id)
和files(id, mandant_id)
开始。
答案 2 :(得分:0)
我使用的是heidisql,而不是phpmyadmin,你的查询在这里运行正常。也许phpmyadmin在解析你的查询时遇到了问题。
编辑:此外,查询长度有限制。如果您的" in" -statement为long,则mysql将返回phpmyadmin应返回的错误。
但是如果phpmyadmin挂起,我会尝试执行你的查询我的mysqlc或另一个像heidisql这样的mysql客户端。