2012-03-13 137 views
0

我有2代表這種結構:優化MySQL查詢與左外連接和GROUP BY

CREATE TABLE `classi` (
    `nome` char(50) NOT NULL DEFAULT '', 
    `padre` char(50) NOT NULL DEFAULT '', 
    `prop` int(11) NOT NULL DEFAULT '0', 
    `metodi` int(11) NOT NULL DEFAULT '0', 
    `descrizione` text, 
    PRIMARY KEY (`nome`), 
    UNIQUE KEY `nome` (`nome`), 
    UNIQUE KEY `padre` (`padre`,`nome`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

CREATE TABLE `prop` (
    `classe` char(50) NOT NULL DEFAULT '', 
    `nome` char(50) NOT NULL DEFAULT '', 
    `tipo` char(1) NOT NULL DEFAULT '', 
    `valori` text, 
    `descrizione` text, 
    PRIMARY KEY (`classe`,`nome`), 
    UNIQUE KEY `speciale` (`classe`,`nome`), 
    UNIQUE KEY `nome` (`classe`,`nome`), 
UNIQUE KEY `tipo` (`classe`,`tipo`,`nome`) 
) 

這裏是我的查詢規則:

  1. 「CLASSI」是主表「prop」是CHILD表的「classi」(1到 N關係在classi.nome - > prop.classe)
  2. 我需要「classi」中的所有記錄並且只有第一個「JOINABLE」 RECORD of「道具「(其中prop.tipo ='A',由prop.tipo命令)
  3. 最後的記錄需要通過classi.nome

責令這是我寫的查詢(和它的作品):

SELECT c.nome, c.prop, c.metodi, p.nome AS pnome, p.tipo 
FROM classi c 
LEFT OUTER JOIN 
(SELECT nome, classe, tipo FROM prop ORDER BY tipo) p 
ON c.nome = p.classe 
WHERE p.tipo = 'A' 
GROUP BY c.nome 
ORDER BY c.nome; 

所以我的最後一個問題是:是有可能進一步優化這個查詢(例如,避免派生表或其他建議)?

請認爲任何解決方案應適用於其他數據庫引擎後(MSSQL,PostgreSQL的,ECC)。所以我需要一個ANSI和便攜的解決方案(或「翻譯」的解決方案)。

預先感謝您的回覆!

+0

另外加上'EXPLAIN'輸出。 – Reactormonk 2012-03-13 10:41:34

+0

什麼是道具的FIRST JOINABLE記錄?您可以通過tipo進行訂購,但也可以通過它進行篩選,訂購A's不會給出有意義的答案。 – 2012-03-14 11:15:28

+0

你是對的尼古拉,試圖想像WHERE子句不存在。對於同樣的「類」(A,B,C,...),我在prop表中有幾個「tipo」記錄,但我只需要第一個(由「tipo」命令)「classe」 C「,例如,對於相同的」類別「記錄,不存在任何」A「或」B「」tipo「記錄) – nerik 2012-03-14 14:46:59

回答

0

爲什麼不乾脆

SELECT c.nome, c.prop, c.metodi, p.nome AS pnome, p.tipo 
FROM classi c 
JOIN prop p 
ON c.nome = p.classe 
WHERE p.tipo = 'A' 
ORDER BY c.nome; 

LEFT JOIN不工作,因爲你必須在正確的表的條件,也沒有必要加入到派生表,因爲條件將採取的其他道具記錄護理。 此外,我不明白這是如何工作,因爲你有一個組,但大多數列沒有分組或聚合。

+0

對原始查詢進行了很好的重寫,但它不包含」僅第一次「可連接」 「道具」# – newtover 2012-03-13 10:57:20

+0

Facepalm :-)錯過了那部分。 – 2012-03-13 10:59:48

+0

不,原始查詢命令由tipo然後過濾'A's only。沒有規定確保只有一條記錄返回'A'。 – 2012-03-13 11:02:18

0

你爲什麼不乾脆做到以下幾點:

SELECT c.nome, c.prop, c.metodi, p.nome AS pnome, p.tipo 
FROM classi c 
LEFT OUTER JOIN 
prop p 
ON c.nome = p.classe 
WHERE p.tipo = 'A' 
GROUP BY c.nome 
ORDER BY c.nome; 
+0

沒有Vikram ...是的,用這種方法查詢會檢索相同數量的行......但是您不能確定實際上加入的道具記錄是第一個排序的tipo列。 – nerik 2012-03-13 14:10:46