这就是我想要实现的目标:
显示最近50名学生及其最便宜的产品。
如果产品不存在,则显示空值。
这是SELECT查询:
SELECT
students.*,
cs.cheapest_id,
cs.cheapest_price
FROM students
LEFT JOIN (SELECT iqs.* FROM (
SELECT
student_id,
id AS cheapest_id,
price AS cheapest_price
FROM products
ORDER BY price ASC
) AS iqs
GROUP BY iqs.student_id) AS cs ON cs.student_id = students.id
ORDER BY students.name DESC
LIMIT 50;
创建表格:
CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `students` VALUES ('1', 'Mark');
INSERT INTO `students` VALUES ('2', 'Chris');
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_id` int(11) DEFAULT NULL,
`price` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `student_id` (`student_id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `products` VALUES ('1', '1', '2');
INSERT INTO `products` VALUES ('2', '1', '3');
结果:
id name cheapest_id cheapest_price
1 Mark 1 2
2 Chris (NULL) (NULL)
问题在于:
如果两个表中有很多记录,则查询非常慢(分钟)。
如果我使用INNER JOIN而不是LEFT JOIN,或者如果我删除“ORDER BY students.name DESC”查询很快。
我在student_id上设置了索引,但仍然非常慢。
有人可以帮忙吗?几天来我一直在努力......
编辑:EXPLAIN的结果
1 PRIMARY students ALL 3 Using temporary; Using filesort
1 PRIMARY <derived2> ALL 2
2 DERIVED <derived3> ALL 4 Using temporary; Using filesort
3 DERIVED products ALL 4 Using filesort
答案 0 :(得分:0)
尝试添加这些索引:
ALTER TABLE `students` ADD INDEX (`id`, `name`);
ALTER TABLE `products` ADD INDEX (`student_id`, `id`, `price`);
并按如下方式编写您的查询:
SELECT students.*,
MIN(products.id) AS cheapest_id,
MIN(products.price) AS cheapest_price
FROM students
LEFT JOIN products ON student_id = students.id
GROUP BY students.id
ORDER BY students.name DESC
LIMIT 50;
您应该阅读有关EXPLAIN SELECT语法以及如何正确索引的内容: https://dev.mysql.com/doc/refman/5.6/en/explain.html https://dev.mysql.com/doc/refman/5.5/en/optimization-indexes.html
使用 EXPLAIN SELET%YOUR QUERY%,您可以看到MySQL如何优化查询以及引擎实际读取数据集的方式。