2013-10-29 23 views
5

La mia domanda riguarda l'ottimizzazione e le buone pratiche di MySQL.MySQL: ORDINA PER CAMPO/GRUPPO PER

Devo ottenere l'elenco di testi tradotti con preferenza di ordine: se non riesco a trovare il testo in inglese, voglio usare il testo francese e se non esiste, voglio usare lo spagnolo.

In altre parole, ho:

id lang text 
1 fr text_FR 
1 en text_EN 
1 es text_ES 
2 fr text_FR2 
3 fr text_FR3 
3 es text_ES3 

E voglio:

id lang text 
1 en text_EN 
2 fr text_FR2 
3 fr text_FR3 

così ho letto alcuni argomenti come this, this, that o that. Ok. Ho provato questo:

SELECT text FROM (
    SELECT id, text 
    FROM translation 
    ORDER BY FIELD(lang, 'en', 'fr', 'es') 
) tt GROUP BY tt.id; 

Ma, quando spiego questa query, posso leggere:

id select_type table partitions type possible_keys key key_len ref rows Extra 
1 PRIMARY <derived2> NULL ALL NULL NULL NULL NULL 4 Using temporary; Using filesort 
2 DERIVED translation NULL ALL PRIMARY PRIMARY 52  1641  Using filesort 

quindi non è ottimizzata, a causa della sottoquery. Posso evitare questa subquery?

risposta

2

Vorrei suggerire JOIN su un tavolo da id per ogni lingua. È possibile utilizzare un LEFT JOIN per consentire risultati nulli. La query continuerà a utilizzare temporaneamente/filesort perché deve eseguire la scansione dell'intera tabella (è possibile utilizzare uno WHERE per limitarlo di più), ma solo per la prima tabella. Le ricerche nelle tabelle unite devono essere veloci.

SELECT 
    COALESCE(en.text, fr.text, es.text, any.text) 
FROM 
    f any 
    LEFT JOIN f en ON (any.id = en.id AND en.lang = 'en') 
    LEFT JOIN f fr ON (any.id = fr.id AND fr.lang = 'fr') 
    LEFT JOIN f es ON (any.id = es.id AND es.lang = 'es') 
GROUP BY any.id; 

http://sqlfiddle.com/#!2/baafc/1

+0

Interessante, non sapeva di 'COALESCE'! – xiankai