Es gibt kein genaues Äquivalent zum Konvertieren einer Postgresql-Abfrage, die SELECT DISTINCT ON in MySQL verwendet.
Postgresql SELECT DISTINCT ON
In Postgresql löscht die folgende Abfrage alle Zeilen, in denen die Ausdrücke (col1, col2, col3)
übereinstimmen, und es wird nur die "erste Spalte Spalte4, Spalte5" für jeden Satz übereinstimmender Zeilen behalten:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
Wenn Ihre Tabelle also so aussieht:
col1 | col2 | col3 | col4 | col5
--------------------------------
1 | 2 | 3 | 777 | 888
1 | 2 | 3 | 888 | 999
3 | 3 | 3 | 555 | 555
Unsere Abfrage behält nur eine Zeile für (1,2,3) und eine Zeile für (3,3,3). Die resultierenden Zeilen sind dann:
col4 | col5
-----------
777 | 888
555 | 555
Bitte beachten Sie, dass die "erste Zeile" jedes Satzes unvorhersehbar ist, unsere erste Zeile könnte auch (888, 999) sein, es sei denn, wir geben eine ORDER BY:
anSELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
(Die DISTINCT on-Ausdrücke müssen mit den ORDER BY-Ausdrücken ganz links übereinstimmen, aber ORDER BY kann zusätzliche Ausdrücke enthalten).
MySQL-Erweiterung für GROUP BY
MySQL erweitert die Verwendung von GROUP BY, sodass wir nicht aggregierte Spalten auswählen können, die nicht in der GROUP BY-Klausel benannt sind. Immer wenn wir nicht aggregierte Spalten auswählen, kann der Server jeden Wert aus jeder Gruppe dieser Spalte auswählen, sodass die resultierenden Werte unbestimmt sind.
Also diese Postgresql-Abfrage:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
kann als äquivalent zu dieser MySQL-Abfrage betrachtet werden:
SELECT col4, col5
FROM tablename
GROUP BY col1, col2, col3
Sowohl Postgresql als auch MySQL geben jeweils die „erste Zeile“ zurück (col1, col2, col3), und in beiden Fällen ist die zurückgegebene Zeile unvorhersehbar, da wir die Klausel nicht angegeben und sortiert haben.
Viele Leute wären sehr versucht, diese Postgresql-Abfrage mit einem ORDER BY:
zu konvertierenSELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
mit diesem hier:
SELECT col4, col5
FROM (
SELECT col1, col2, col3, col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
) s
GROUP BY col1, col2, col3
Die Idee hier ist, ein ORDER BY auf eine Unterabfrage anzuwenden, sodass MySQL, wenn es nach col1, col2, col3 gruppiert, den ersten gefundenen Wert für col4 und col5 behält. Die Idee ist gut, aber sie ist falsch! MySQL kann jeden Wert für col4 und col5 frei wählen, und wir wissen nicht, welche die ersten Werte sind, auf die wir stoßen, es hängt vom Optimierer ab. Also würde ich es folgendermaßen korrigieren:
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
aber das wird langsam komplizierter.
Fazit
Als allgemeine Regel gilt, dass es keinen genauen Weg gibt, eine Postgresql-Abfrage in eine MySQL-Abfrage zu konvertieren, aber es gibt viele Problemumgehungen, die resultierende Abfrage kann so einfach wie die ursprüngliche sein oder sehr kompliziert werden, aber es hängt davon ab die Abfrage selbst.