Nie ma dokładnego odpowiednika konwersji zapytania Postgresql korzystającego z SELECT DISTINCT ON na MySQL.
Postgresql WYBIERZ WYRÓŻNIENIE NA
W Postgresql poniższe zapytanie wyeliminuje wszystkie wiersze, w których wyrażenia (col1, col2, col3)
dopasowania, a dla każdego zestawu dopasowanych wierszy zostanie zachowany tylko wiersz „pierwszy col4, col5”:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
Więc jeśli Twój stół wygląda tak:
col1 | col2 | col3 | col4 | col5
--------------------------------
1 | 2 | 3 | 777 | 888
1 | 2 | 3 | 888 | 999
3 | 3 | 3 | 555 | 555
nasze zapytanie zachowa tylko jeden wiersz dla (1,2,3) i jeden wiersz dla (3,3,3). Wynikowe wiersze będą wtedy wyglądały następująco:
col4 | col5
-----------
777 | 888
555 | 555
proszę zauważyć, że "pierwszy rząd" każdego zestawu jest nieprzewidywalny, nasz pierwszy rząd może być również (888, 999), chyba że określimy ORDER BY:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
(DISTINCT na wyrażeniach musi odpowiadać wyrażeniom ORDER BY znajdującym się najbardziej po lewej stronie, ale ORDER BY może zawierać dodatkowe wyrażenia).
Rozszerzenie MySQL do GROUP BY
MySQL rozszerza użycie GROUP BY, dzięki czemu możemy wybrać niezagregowane kolumny, których nie wymieniono w klauzuli GROUP BY. Za każdym razem, gdy wybieramy kolumny niezagregowane, serwer może swobodnie wybrać dowolną wartość z każdej grupy z tej kolumny, więc wynikowe wartości będą nieokreślone.
Więc to zapytanie Postgresql:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
można uznać za równoważne z tym zapytaniem MySQL:
SELECT col4, col5
FROM tablename
GROUP BY col1, col2, col3
zarówno Postgresql, jak i MySQL zwrócą "Pierwszy wiersz" dla każdego z nich (col1, col2, col3) i w obu przypadkach zwrócony wiersz jest nieprzewidywalny, ponieważ nie określiliśmy i nie uporządkowaliśmy klauzuli.
Wiele osób kusiłoby, aby przekonwertować to zapytanie Postgresql za pomocą ORDER BY:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
z tym:
SELECT col4, col5
FROM (
SELECT col1, col2, col3, col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
) s
GROUP BY col1, col2, col3
Pomysł polega na tym, aby zastosować ORDER BY do podzapytania, aby kiedy MySQL grupował według col1, col2, col3, zachował pierwszą napotkaną wartość dla col4 i col5. Pomysł jest dobry, ale zły! MySQL może swobodnie wybrać dowolną wartość dla col4 i col5, a nie wiemy, które wartości są pierwszymi napotkanymi, zależy to od optymalizatora. Więc poprawiłbym to do tego:
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 to zaczyna się komplikować.
Wniosek
Zasadniczo nie ma dokładnego sposobu na przekonwertowanie zapytania Postgresql na zapytanie MySQL, ale istnieje wiele obejść, wynikowe zapytanie może być tak proste jak oryginalne lub może stać się bardzo skomplikowane, ale zależy to od samo zapytanie.