sql >> Databáze >  >> RDS >> PostgreSQL

Převod dotazů SELECT DISTINCT ON z Postgresql na MySQL

Neexistuje přesný ekvivalent pro převod dotazu Postgresql, který využívá SELECT DISTINCT ON na MySQL.

Postgresql SELECT DISTINCT ON

V Postgresql následující dotaz odstraní všechny řádky, kde jsou výrazy (col1, col2, col3) shodu a zachová pouze „první řádek4, sloupec5“ pro každou sadu odpovídajících řádků:

SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename

Takže pokud je váš stůl takový:

col1 | col2 | col3 | col4 | col5
--------------------------------
1    | 2    | 3    | 777  | 888
1    | 2    | 3    | 888  | 999
3    | 3    | 3    | 555  | 555

náš dotaz zachová pouze jeden řádek pro (1,2,3) a jeden řádek pro (3,3,3). Výsledné řádky pak budou:

col4 | col5
-----------
777  | 888
555  | 555

všimněte si prosím, že "první řada" každé sady je nepředvídatelná, naše první řada může být také (888, 999), pokud neurčíme ORDER BY:

SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4

(DISTINCT na výrazech se musí shodovat s výrazy ORDER BY zcela vlevo, ale ORDER BY může obsahovat další výrazy).

Rozšíření MySQL na GROUP BY

MySQL rozšiřuje použití GROUP BY, takže můžeme vybrat neagregované sloupce, které nejsou uvedeny v klauzuli GROUP BY. Kdykoli vybereme neagregované sloupce, server si může vybrat libovolnou hodnotu z každé skupiny z daného sloupce, takže výsledné hodnoty budou neurčité.

Takže tento dotaz Postgresql:

SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename

lze považovat za ekvivalent tohoto dotazu MySQL:

SELECT col4, col5
FROM tablename
GROUP BY col1, col2, col3

Postgresql i MySQL vrátí "První řádek" pro každý (col1, col2, col3) a v obou případech je vrácený řádek nepředvídatelný, protože jsme nespecifikovali a neseřadili podle klauzule.

Mnoho lidí by bylo velmi v pokušení převést tento dotaz Postgresql pomocí příkazu ORDER BY:

SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4

s tímto:

SELECT col4, col5
FROM (
  SELECT col1, col2, col3, col4, col5
  FROM tablename
  ORDER BY col1, col2, col3, col4
) s
GROUP BY col1, col2, col3

myšlenkou je použít ORDER BY na poddotaz, takže když MySQL seskupuje podle col1, col2, col3, uchová první zjištěnou hodnotu pro col4 a col5. Nápad je dobrý, ale je špatný! MySQL si může vybrat libovolnou hodnotu pro col4 a col5 a nevíme, které hodnoty jsou první, záleží to na optimalizátoru. Takže bych to opravil takto:

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 začíná to být složitější.

Závěr

Obecně platí, že neexistuje přesný způsob, jak převést dotaz Postgresql na dotaz MySQL, ale existuje mnoho řešení, výsledný dotaz může být stejně jednoduchý jako původní dotaz nebo se může stát velmi komplikovaným, ale záleží na samotný dotaz.



  1. Jak mohu vložit více řádků do oracle s hodnotou sekvence?

  2. MySQL vrací pouze jeden řádek

  3. Jak se vyhnout vkládání duplicitních záznamů do MySQL

  4. Počítejte záznamy pro každý měsíc v roce