sql >> Base de Datos >  >> RDS >> PostgreSQL

Conversión de consultas SELECT DISTINCT ON de Postgresql a MySQL

No existe un equivalente exacto para convertir una consulta de Postgresql que utilice SELECT DISTINCT ON en MySQL.

Postgresql SELECCIONE DISTINTO EN

En Postgresql, la siguiente consulta eliminará todas las filas donde las expresiones (col1, col2, col3) coincidencia, y solo mantendrá la "primera fila col4, col5" para cada conjunto de filas coincidentes:

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

Así que si tu mesa es así:

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

nuestra consulta mantendrá solo una fila para (1,2,3) y una fila para (3,3,3). Las filas resultantes serán entonces:

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

tenga en cuenta que la "primera fila" de cada conjunto es impredecible, nuestra primera fila también podría ser (888, 999) a menos que especifiquemos un ORDEN POR:

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

(las expresiones DISTINCT on deben coincidir con las expresiones ORDER BY que se encuentran más a la izquierda, pero ORDER BY puede contener expresiones adicionales).

Extensión MySQL para GROUP BY

MySQL amplía el uso de GROUP BY para que podamos seleccionar columnas no agregadas no nombradas en la cláusula GROUP BY. Siempre que seleccionamos columnas no agregadas, el servidor es libre de elegir cualquier valor de cada grupo de esa columna, por lo que los valores resultantes serán indeterminados.

Así que esta consulta de Postgresql:

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

puede considerarse equivalente a esta consulta de MySQL:

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

tanto Postgresql como MySQL devolverán la "Primera fila" para cada uno (col1, col2, col3), y en ambos casos la fila devuelta es impredecible porque no especificamos ni ordenamos por cláusula.

Mucha gente estaría muy tentada a convertir esta consulta de Postgresql con ORDER BY:

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

con este:

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

la idea aquí es aplicar ORDER BY a una subconsulta para que cuando MySQL agrupe por col1, col2, col3, mantenga el primer valor encontrado para col4 y col5. La idea es buena, ¡pero está mal! MySQL es libre de elegir cualquier valor para col4 y col5, y no sabemos cuáles son los primeros valores encontrados, depende del optimizador. Así que lo corregiría a esto:

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

pero esto empieza a complicarse.

Conclusión

Como regla general, no hay una forma exacta de convertir una consulta de Postgresql en una consulta de MySQL, pero hay muchas soluciones alternativas, la consulta resultante puede ser tan simple como la original o puede volverse muy complicada, pero depende de la consulta en sí.