2009-08-28 106 views
0

嘿。我以1:n的關係得到了這兩張表。GROUP BY優化

CREATE TABLE IF NOT EXISTS `de_locations` (
`id` int(11) NOT NULL auto_increment, 
`user_id` int(11) default NULL, 
`author_id` int(11) NOT NULL, 
`city_id` int(11) NOT NULL, 
`district_id` int(11) NOT NULL, 
`title` varchar(150) collate utf8_unicode_ci NOT NULL, 
`description` tinytext collate utf8_unicode_ci, 
`lat` double NOT NULL, 
`lng` double NOT NULL, 
`stars` double default '0', 
`comments` mediumint(9) default '0', 
`flag` tinyint(4) default '0', 
PRIMARY KEY (`id`), 
KEY `user_id` (`user_id`), 
KEY `flag` (`flag`), 
KEY `rating_district` (`district_id`,`stars`,`comments`), 
KEY `rating_city` (`city_id`,`stars`,`comments`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=15 ; 

CREATE TABLE IF NOT EXISTS `de_location2category` (
`id` int(11) NOT NULL auto_increment, 
`location_id` int(11) NOT NULL, 
`cat_id` mediumint(9) NOT NULL, 
PRIMARY KEY (`id`), 
UNIQUE KEY `rel` (`location_id`,`cat_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=14 ; 

甲位置可以被放置在一個以上的類別。

例如:

位置:「必勝客」 分類:「意大利食品」,「快餐」

這些類別是父類食品的兒童類。

現在我想選擇類別食物內的所有位置。

SELECT a.id, a.title, a.description, a.street, a.hnr, ROUND(a.stars) as stars, a.comments, a.lat, a.lng 
FROM de_locations as a 
INNER JOIN de_location2category as b 
ON b.location_id = a.id 
WHERE b.cat_id BETWEEN 0 AND 100 
AND a.city_id = 1000 
GROUP BY a.id 
ORDER BY a.stars DESC, a.comments DESC 

我需要GROUP BY,因爲如果他們涉及到多個類別,我不想要重複的位置。但是這個查詢構建一個臨時表並使用filesort。如果我離開了GROUP BY一切都很好,但我需要它...

有我添加其他指標?或者我的計劃有什麼問題? 你會如何解決這個問題?非常感謝。

+0

所以呢?這就是關係數據庫的工作方式。那有什麼問題?你還建議刪除重複項目嗎? – 2009-08-28 10:05:40

+0

http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html「在某些情況下,MySQL不能使用索引來解決ORDER BY,儘管它仍然使用索引來查找行那場比賽的WHERE子句這些情況包括以下內容:*您不同的關鍵字使用ORDER BY:?SELECT * FROM T1 ORDER BY鍵1,鍵2; *」 – Amber 2009-08-28 10:15:18

+0

‘What's錯’表現。在一個簡單的SELECT中,GROUP BY並不總是強制臨時表。在這種情況下,沒有辦法達到這個目的嗎? 此外,索引「rating_city」不與GROUP BY一起使用。 – Status4 2009-08-28 10:15:44

回答

0

爲什麼不直接使用DISTINCT a.id?

+0

與GROUP BY相同的結果:臨時表和文件夾 – Status4 2009-08-28 10:13:50

+0

是的,這是因爲您按多個鍵進行排序而得到的。 DISTINCT只是描述了你實際上想要實現的更好的GROUP BY。 – Amber 2009-08-28 10:16:16

+0

我是否正確地解決了問題:我在WHERE子句中使用索引「rel」,在ORDER BY子句中使用索引「rating_city」? 因此,我沒有機會只改變索引? 所以我必須忍受臨時表和文件夾? 對不起,有一些語言問題... – Status4 2009-08-28 10:37:39

1

我覺得你的問題是,查詢速度很慢。無需擔心臨時文件和文件夾,但爲什麼查詢速度很慢。 添加EXPLAIN {yourquery}的輸出,以便我們可以檢查到底發生了什麼。

或者你也可以嘗試一個子查詢:「但這查詢構建了一個臨時表,並使用文件排序」

SELECT a.id, a.title, a.description, a.street, a.hnr, ROUND(a.stars) as stars, a.comments, a.lat, a.lng 
FROM de_locations as a 
WHERE 
a.id IN (SELECT DISTINCT b.location_id FROM de_location2category as b WHERE b.cat_id BETWEEN 0 AND 100) 
AND a.city_id = 1000 
GROUP BY a.id 
ORDER BY a.stars DESC, a.comments DESC 
+0

嘿周杰倫,謝謝。我會試試這個。 – Status4 2011-02-11 19:31:05