Er is geen exact equivalent voor het converteren van een Postgresql-query die gebruikmaakt van SELECT DISTINCT ON naar MySQL.
Postgresql SELECTEER DISTINCT ON
In Postgresql elimineert de volgende query alle rijen waarin de uitdrukkingen (col1, col2, col3)
overeenkomen, en het behoudt alleen de "eerste col4, col5 rij" voor elke set overeenkomende rijen:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
Dus als je tafel er zo uitziet:
col1 | col2 | col3 | col4 | col5
--------------------------------
1 | 2 | 3 | 777 | 888
1 | 2 | 3 | 888 | 999
3 | 3 | 3 | 555 | 555
onze query houdt slechts één rij voor (1,2,3) en één rij voor (3,3,3). De resulterende rijen zijn dan:
col4 | col5
-----------
777 | 888
555 | 555
houd er rekening mee dat de "eerste rij" van elke set onvoorspelbaar is, onze eerste rij kan dat ook zijn (888, 999), tenzij we een ORDER BY specificeren:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
(De DISTINCT op expressies moet overeenkomen met de meest linkse ORDER BY-expressies, maar de ORDER BY kan extra expressies bevatten).
MySQL-extensie voor GROUP BY
MySQL breidt het gebruik van GROUP BY uit, zodat we niet-geaggregeerde kolommen kunnen selecteren die niet in de GROUP BY-clausule worden genoemd. Telkens wanneer we niet-geaggregeerde kolommen selecteren, is de server vrij om elke waarde uit elke groep uit die kolom te kiezen, dus de resulterende waarden zullen onbepaald zijn.
Dus deze Postgresql-query:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
kan worden beschouwd als gelijkwaardig aan deze MySQL-query:
SELECT col4, col5
FROM tablename
GROUP BY col1, col2, col3
zowel Postgresql als MySQL retourneert de "Eerste rij" voor elk (col1, col2, col3), en in beide gevallen is de geretourneerde rij onvoorspelbaar omdat we niet hebben gespecificeerd en geordend op clausule.
Veel mensen zouden in de verleiding komen om deze Postgresql-query om te zetten met een ORDER BY:
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
met deze:
SELECT col4, col5
FROM (
SELECT col1, col2, col3, col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
) s
GROUP BY col1, col2, col3
het idee hier is om een ORDER BY toe te passen op een subquery, zodat wanneer MySQL groepeert op col1, col2, col3, het de eerste gevonden waarde voor col4 en col5 behoudt. Het idee is goed, maar het is verkeerd! MySQL is vrij om elke waarde voor col4 en col5 te kiezen, en we weten niet welke de eerste waarden zijn die we tegenkomen, het hangt af van de optimizer. Dus ik zou het als volgt corrigeren:
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
maar dit begint ingewikkelder te worden.
Conclusie
Als algemene regel geldt dat er geen exacte manier is om een Postgresql-query om te zetten in een MySQL-query, maar er zijn veel oplossingen:de resulterende query kan net zo eenvoudig zijn als de oorspronkelijke of het kan erg ingewikkeld worden, maar het hangt af van de vraag zelf.