sql >> Database teknologi >  >> RDS >> PostgreSQL

Konvertering af SELECT DISTINCT ON-forespørgsler fra Postgresql til MySQL

Der er ikke en nøjagtig ækvivalent til at konvertere en Postgresql-forespørgsel, der gør brug af SELECT DISTINCT ON til MySQL.

Postgresql VÆLG DISTINCT ON

I Postgresql vil følgende forespørgsel eliminere alle rækker, hvor udtrykkene (col1, col2, col3) match, og det vil kun beholde den "første col4, col5 row" for hvert sæt matchede rækker:

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

Så hvis dit bord er sådan her:

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

vores forespørgsel vil kun beholde en række for (1,2,3) og en række for (3,3,3). De resulterende rækker vil derefter være:

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

Bemærk venligst, at den "første række" i hvert sæt er uforudsigelig, vores første række kan også være (888, 999), medmindre vi angiver en BESTILLING AF:

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

(DISTINCT på udtryk skal matche ORDER BY-udtrykkene længst til venstre, men ORDER BY kan indeholde yderligere udtryk).

MySQL-udvidelse til GROUP BY

MySQL udvider brugen af ​​GROUP BY, så vi kan vælge ikke-aggregerede kolonner, der ikke er navngivet i GROUP BY-sætningen. Når vi vælger ikke-aggregerede kolonner, kan serveren frit vælge en hvilken som helst værdi fra hver gruppe fra den kolonne, så de resulterende værdier vil være ubestemte.

Så denne Postgresql-forespørgsel:

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

kan betragtes som svarende til denne MySQL-forespørgsel:

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

både Postgresql og MySQL vil returnere "Første række" for hver (col1, col2, col3), og i begge tilfælde er den returnerede række uforudsigelig, fordi vi ikke specificerede og sorterede efter klausul.

Mange mennesker ville være meget fristet til at konvertere denne Postgresql-forespørgsel med en ORDER BY:

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

med denne:

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

Ideen her er at anvende en ORDER BY til en underforespørgsel, så når MySQL grupperer efter col1, col2, col3, vil den beholde den først stødte værdi for col4 og col5. Ideen er god, men den er forkert! MySQL kan frit vælge en hvilken som helst værdi for col4 og col5, og vi ved ikke, hvilke værdier der først støder på, det afhænger af optimizeren. Så jeg ville rette det til dette:

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

men dette begynder at blive mere kompliceret.

Konklusion

Som en generel regel er der ikke en nøjagtig måde at konvertere en Postgresql-forespørgsel til en MySQL-forespørgsel, men der er mange løsninger, den resulterende forespørgsel kan være lige så enkel som den originale, eller den kan blive meget kompliceret, men det afhænger af selve forespørgslen.



  1. Trin du skal tage, hvis du har et MySQL-udfald

  2. Vælger du en selvstændig fuldtekstsøgeserver:Sphinx eller SOLR?

  3. Hvis du kunne stille MS Access-teamet ethvert spørgsmål, hvad ville det så være?

  4. Datokonvertering og kultur:Forskellen mellem DATE og DATETIME