sql >> Base de Datos >  >> RDS >> Mysql

Usar DISTINCT dentro de JOIN está creando problemas

Un enfoque es usar una vista en línea, como la consulta que ya tiene. Pero en lugar de usar DISTINCT, usaría GROUP BY para eliminar duplicados. La vista en línea más simple para satisfacer sus requisitos sería:

( SELECT n.item_number, n.name, n.type_code
    FROM itpitnam n
   GROUP BY n.item_number
) itpitnam

Aunque no es determinista en cuanto a qué fila de itpitnam se recuperan los valores de name y type_code. Una vista en línea más elaborada puede hacer esto más específico.

Otro enfoque común para este tipo de problema es usar una subconsulta correlacionada en la lista SELECT. Para devolver un pequeño conjunto de filas, esto puede funcionar razonablemente bien. Pero para devolver conjuntos grandes, existen enfoques más eficientes.

SELECT i.identifier
     , i.name
     , i.subtitle
     , i.description
     , i.itemimg 
     , i.mainprice
     , i.upc
     , i.isbn
     , i.weight
     , i.pages
     , i.publisher
     , i.medium_abbr
     , i.medium_desc
     , i.series_abbr
     , i.series_desc
     , i.voicing_desc
     , i.pianolevel_desc
     , i.bandgrade_desc
     , i.category_code
     , r.overall_ranking
     , ( SELECT n1.name
           FROM itpitnam n1
          WHERE n1.item_number = r.item_number
          ORDER BY n1.type_code, n1.name
          LIMIT 1
       ) AS artist
     , ( SELECT n2.type_code
           FROM itpitnam n2
          WHERE n2.item_number = r.item_number
          ORDER BY n2.type_code, n2.name
          LIMIT 1
       ) AS type_code
  FROM itpitems i
  JOIN itprank r
    ON r.item_number = i.identifier
 WHERE mainprice > 1
 LIMIT 3

Esa consulta devolverá el conjunto de resultados especificado, con una diferencia significativa. La consulta original muestra un INNER JOIN al itpitnam mesa. Eso significa que se devolverá una fila SOLO si hay una fila coincidente en el itpitnam mesa. La consulta anterior, sin embargo, emula un OUTER JOIN, la consulta devolverá una fila cuando no se encuentre ninguna fila coincidente en itpitnam .

ACTUALIZAR

Para obtener el mejor rendimiento de esas subconsultas correlacionadas, querrá tener disponible un índice apropiado,

... ON itpitnam (item_number, type_code, name)

Ese índice es el más apropiado porque es un "índice de cobertura", la consulta se puede satisfacer completamente desde el índice sin hacer referencia a las páginas de datos en la tabla subyacente, y hay un predicado de igualdad en la columna inicial y un ORDEN POR en las siguientes dos columnas, por lo que evitará una operación de "clasificación".

--

Si tiene una garantía de que el type_code o name columna en la tabla itpitnam NO ES NULO, puede agregar un predicado para eliminar las filas que "faltan" una fila coincidente, por ejemplo,

HAVING artist IS NOT NULL

(Agregar eso probablemente tendrá un impacto en el rendimiento). En ausencia de ese tipo de garantía, necesitaría agregar un INNER JOIN o un predicado que pruebe la existencia de una fila coincidente, para obtener un comportamiento de INNER JOIN.