Não há um equivalente exato para converter uma consulta Postgresql que use SELECT DISTINCT ON para MySQL.
Postgresql SELECT DISTINCT ON
No Postgresql, a consulta a seguir eliminará todas as linhas onde as expressões
(col1, col2, col3)
match, e manterá apenas a "primeira col4, col5 row" para cada conjunto de linhas correspondentes:SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
Então, se sua tabela estiver assim:
col1 | col2 | col3 | col4 | col5
--------------------------------
1 | 2 | 3 | 777 | 888
1 | 2 | 3 | 888 | 999
3 | 3 | 3 | 555 | 555
nossa consulta manterá apenas uma linha para (1,2,3) e uma linha para (3,3,3). As linhas resultantes serão então:
col4 | col5
-----------
777 | 888
555 | 555
observe que a "primeira linha" de cada conjunto é imprevisível, nossa primeira linha também pode ser (888, 999), a menos que especifiquemos um ORDER BY:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
(o DISTINCT nas expressões deve corresponder às expressões ORDER BY mais à esquerda, mas o ORDER BY pode conter expressões adicionais).
Extensão MySQL para GROUP BY
O MySQL estende o uso de GROUP BY para que possamos selecionar colunas não agregadas não nomeadas na cláusula GROUP BY. Sempre que selecionamos colunas não agregadas o servidor fica livre para escolher qualquer valor de cada grupo daquela coluna, portanto os valores resultantes serão indeterminados.
Então esta consulta Postgresql:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
pode ser considerado equivalente a esta consulta MySQL:
SELECT col4, col5
FROM tablename
GROUP BY col1, col2, col3
tanto o Postgresql quanto o MySQL retornarão a "Primeira linha" para cada um (col1, col2, col3), e em ambos os casos a linha retornada é imprevisível porque não especificamos e ordenamos por cláusula.
Muitas pessoas ficariam muito tentadas a converter esta consulta do Postgresql com um ORDER BY:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
com este:
SELECT col4, col5
FROM (
SELECT col1, col2, col3, col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
) s
GROUP BY col1, col2, col3
a idéia aqui é aplicar um ORDER BY a uma subconsulta para que quando o MySQL agrupar por col1, col2, col3 ele mantenha o primeiro valor encontrado para col4 e col5. A ideia é boa, mas está errada! O MySQL é livre para escolher qualquer valor para col4 e col5, e não sabemos quais são os primeiros valores encontrados, depende do otimizador. Então eu corrigiria para isso:
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
mas isso está começando a ficar mais complicado.
Conclusão
Como regra geral, não há uma maneira exata de converter uma consulta Postgresql em uma consulta MySQL, mas existem muitas soluções alternativas, a consulta resultante pode ser tão simples quanto a original ou pode se tornar muito complicada, mas depende de a própria consulta.