2013-10-29 11 views
5

Moje pytanie dotyczy optymalizacji MySQL i dobrych praktyk.MySQL: ORDER BY FIELD/GROUP BY

Muszę uzyskać przetłumaczoną listę tekstów z preferencją zamówienia: jeśli nie mogę znaleźć tekstu w języku angielskim, chcę użyć francuskiego tekstu, a jeśli nie istnieje, chcę użyć hiszpańskiego.

Innymi słowy, mam:

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 

I chcę:

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

Więc czytam niektóre tematy jak this, this, that lub that. Ok. Próbowałem to:

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

Ale kiedy to wyjaśnić kwerendy, mogę czytać:

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 

Więc to nie jest zoptymalizowany, ponieważ podzapytania. Czy mogę uniknąć tego podkwerendy?

Odpowiedz

2

Proponuję JOIN na stole przez id dla każdego języka. Możesz użyć wartości LEFT JOIN, aby umożliwić zerowanie wyników. Zapytanie nadal będzie używać pliku tymczasowego/filesort, ponieważ musi przeskanować całą tabelę (możesz użyć parametru WHERE, aby ograniczyć to więcej), ale tylko dla pierwszej tabeli. Wyszukiwanie na połączonych tabelach powinno być szybkie.

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

Ciekawe, nie wiedziałem o 'COALESCE'! – xiankai