Il n'y a pas d'équivalent exact pour convertir une requête Postgresql qui utilise SELECT DISTINCT ON en MySQL.
Postgresql SELECT DISTINCT ON
Dans Postgresql, la requête suivante éliminera toutes les lignes où les expressions (col1, col2, col3)
match, et il ne conservera que la "première ligne col4, col5" pour chaque ensemble de lignes correspondantes :
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
Donc, si votre table ressemble à ceci :
col1 | col2 | col3 | col4 | col5
--------------------------------
1 | 2 | 3 | 777 | 888
1 | 2 | 3 | 888 | 999
3 | 3 | 3 | 555 | 555
notre requête ne conservera qu'une ligne pour (1,2,3) et une ligne pour (3,3,3). Les lignes résultantes seront alors :
col4 | col5
-----------
777 | 888
555 | 555
veuillez noter que la "première ligne" de chaque ensemble est imprévisible, notre première ligne peut également être (888, 999) à moins que nous ne spécifions un ORDER BY :
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
(les expressions DISTINCT on doivent correspondre aux expressions ORDER BY les plus à gauche, mais ORDER BY peut contenir des expressions supplémentaires).
Extension MySQL pour GROUP BY
MySQL étend l'utilisation de GROUP BY afin que nous puissions sélectionner des colonnes non agrégées non nommées dans la clause GROUP BY. Chaque fois que nous sélectionnons des colonnes non agrégées, le serveur est libre de choisir n'importe quelle valeur de chaque groupe de cette colonne, de sorte que les valeurs résultantes seront indéterminées.
Donc cette requête Postgresql :
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
peut être considéré comme équivalent à cette requête MySQL :
SELECT col4, col5
FROM tablename
GROUP BY col1, col2, col3
Postgresql et MySQL renverront tous deux la "première ligne" pour chacun (col1, col2, col3), et dans les deux cas, la ligne renvoyée est imprévisible car nous n'avons pas spécifié et ordonné par clause.
Beaucoup de gens seraient très tentés de convertir cette requête Postgresql avec un ORDER BY :
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
avec celui-ci :
SELECT col4, col5
FROM (
SELECT col1, col2, col3, col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
) s
GROUP BY col1, col2, col3
l'idée ici est d'appliquer un ORDER BY à une sous-requête afin que lorsque MySQL groupe par col1, col2, col3, il conserve la première valeur rencontrée pour col4 et col5. L'idée est bonne, mais elle est fausse ! MySQL est libre de choisir n'importe quelle valeur pour col4 et col5, et nous ne savons pas quelles sont les premières valeurs rencontrées, cela dépend de l'optimiseur. Je corrigerais donc ceci :
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
mais cela commence à se compliquer.
Conclusion
En règle générale, il n'y a pas de moyen exact de convertir une requête Postgresql en requête MySQL, mais il existe de nombreuses solutions de contournement, la requête résultante peut être aussi simple que la requête d'origine ou elle peut devenir très compliquée, mais cela dépend de la requête elle-même.