这是我的问题的SQL小提琴:http://sqlfiddle.com/#!9/8ad87/2
我有桌子:群组,优惠和 offers_groups 。
组具有名称,但这些名称具有分配给它们的特殊ID。 Id不是自动递增的,它们是以这种方式预定义的。
以下是群组表格的一小部分:
id name
0300000 Agro
0310000 Fruits
0311000 Peach
0320000 Vegetables
在商品表中存储了由人和公司提供的商品:
id offer
1 Selling fruits
2 Selling peanuts
3 Selling Vegetables
4 Selling peach
5 We do Agro
6 We sell Peach
7 We sell Vegetables
8 We transport Vegetables
9 We transport Peaches
和 offers_groups 表负责连接这两个:
id offer_id group_id
1 1 3100000
2 2 0300000
3 3 0311000
4 4 0300000
5 5 0311000
6 6 0320000
7 7 0320000
8 3 0311000
我需要计算哪些群组拥有最多优惠,并将这些群组展示给用户。
这是我的问题:
SELECT og.id, og.offer_id, og.group_id,
o.id, o.offer,
g.id, g.name,
COUNT(og.offer_id) AS offersCount
FROM `offers_groups` og
JOIN `offers` o ON og.offer_id = o.id
JOIN `groups` g ON og.group_id = g.id
GROUP BY og.group_id
ORDER BY offersCount DESC
LIMIT 2
我的SQL Fiddle中的代码正在工作,我认为它给了我正确的结果,但在真实的数据库中,这些表有很多数据,这个查询执行25秒。而且我不相信这是因为列索引,对吧?我希望有些专家可以告诉我我的查询是否设计得很糟糕。在获得正确结果的同时,我能做些什么来加快速度吗?
由于
答案 0 :(得分:1)
首先,select
中的所有列都没有意义。它们应该只处于“组”级别,而不是“提供组”级别。所以,让我关注这个问题:
SELECT g.id, g.name,
COUNT(og.offer_id) AS offersCount
FROM `offers_groups` og JOIN
`offers` o
ON og.offer_id = o.id JOIN
`groups` g
ON og.group_id = g.id
GROUP BY g.id
ORDER BY offersCount DESC
LIMIT 2;
其次,在任何结构合理的数据库中,您实际上并不需要offers
表 - 外键关系应该确保行实际存在。所以,试试这个:
SELECT g.id, g.name,
COUNT(og.offer_id) AS offersCount
FROM `offers_groups` og JOIN
`groups` g
ON og.group_id = g.id
GROUP BY g.id
ORDER BY offersCount DESC
LIMIT 2;
然后,根据您的SQL Fiddle,您的表上没有索引。将所有id
定义为主键。例如:
CREATE TABLE IF NOT EXISTS `offers` (
`id` int(11) NOT NULL PRIMARY KEY,
`offer` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10 ;
使用主键可以解决您的性能问题。