Neexistuje přesný ekvivalent pro převod dotazu Postgresql, který využívá SELECT DISTINCT ON na MySQL.
Postgresql SELECT DISTINCT ON
V Postgresql následující dotaz odstraní všechny řádky, kde jsou výrazy (col1, col2, col3)
shodu a zachová pouze „první řádek4, sloupec5“ pro každou sadu odpovídajících řádků:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
Takže pokud je váš stůl takový:
col1 | col2 | col3 | col4 | col5
--------------------------------
1 | 2 | 3 | 777 | 888
1 | 2 | 3 | 888 | 999
3 | 3 | 3 | 555 | 555
náš dotaz zachová pouze jeden řádek pro (1,2,3) a jeden řádek pro (3,3,3). Výsledné řádky pak budou:
col4 | col5
-----------
777 | 888
555 | 555
všimněte si prosím, že "první řada" každé sady je nepředvídatelná, naše první řada může být také (888, 999), pokud neurčíme ORDER BY:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
(DISTINCT na výrazech se musí shodovat s výrazy ORDER BY zcela vlevo, ale ORDER BY může obsahovat další výrazy).
Rozšíření MySQL na GROUP BY
MySQL rozšiřuje použití GROUP BY, takže můžeme vybrat neagregované sloupce, které nejsou uvedeny v klauzuli GROUP BY. Kdykoli vybereme neagregované sloupce, server si může vybrat libovolnou hodnotu z každé skupiny z daného sloupce, takže výsledné hodnoty budou neurčité.
Takže tento dotaz Postgresql:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
lze považovat za ekvivalent tohoto dotazu MySQL:
SELECT col4, col5
FROM tablename
GROUP BY col1, col2, col3
Postgresql i MySQL vrátí "První řádek" pro každý (col1, col2, col3) a v obou případech je vrácený řádek nepředvídatelný, protože jsme nespecifikovali a neseřadili podle klauzule.
Mnoho lidí by bylo velmi v pokušení převést tento dotaz Postgresql pomocí příkazu ORDER BY:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
s tímto:
SELECT col4, col5
FROM (
SELECT col1, col2, col3, col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
) s
GROUP BY col1, col2, col3
myšlenkou je použít ORDER BY na poddotaz, takže když MySQL seskupuje podle col1, col2, col3, uchová první zjištěnou hodnotu pro col4 a col5. Nápad je dobrý, ale je špatný! MySQL si může vybrat libovolnou hodnotu pro col4 a col5 a nevíme, které hodnoty jsou první, záleží to na optimalizátoru. Takže bych to opravil takto:
SELECT t1.col4, t1.col5
FROM tablename t1 INNER JOIN (SELECT col1, col2, col3, MIN(col4) as m_col4
FROM tablename
GROUP BY col1, col2, col3) s
ON t1.col1=s.col1
AND t1.col2=s.col2
AND t1.col3=s.col3
AND t1.col4=s.m_col4
GROUP BY
t1.col1, t1.col2, t1.col3, t1.col4
ale začíná to být složitější.
Závěr
Obecně platí, že neexistuje přesný způsob, jak převést dotaz Postgresql na dotaz MySQL, ale existuje mnoho řešení, výsledný dotaz může být stejně jednoduchý jako původní dotaz nebo se může stát velmi komplikovaným, ale záleží na samotný dotaz.