Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Usar DISTINCT dentro de JOIN está criando problemas


Uma abordagem é usar uma visualização em linha, como a consulta que você já tem. Mas em vez de usar DISTINCT, você usaria um GROUP BY para eliminar duplicatas. A visualização em linha mais simples para atender aos seus requisitos seria:
( SELECT n.item_number, n.name, n.type_code
    FROM itpitnam n
   GROUP BY n.item_number
) itpitnam

Embora não seja determinístico sobre qual linha de itpitnam os valores para name e type_code são recuperados. Uma visualização em linha mais elaborada pode tornar isso mais específico.

Outra abordagem comum para esse tipo de problema é usar uma subconsulta correlacionada na lista SELECT. Para retornar um pequeno conjunto de linhas, isso pode funcionar razoavelmente bem. Mas para devolver conjuntos grandes, existem abordagens mais 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

Essa consulta retornará o conjunto de resultados especificado, com uma diferença significativa. A consulta original mostra um INNER JOIN para o itpitnam tabela. Isso significa que uma linha será retornada SOMENTE se houver uma linha correspondente no itpitnam tabela. A consulta acima, no entanto, emula um OUTER JOIN, a consulta retornará uma linha quando não houver nenhuma linha correspondente encontrada em itpitnam .

ATUALIZAÇÃO


Para obter o melhor desempenho dessas subconsultas correlacionadas, você desejará um índice apropriado disponível,
... ON itpitnam (item_number, type_code, name)

Esse índice é mais apropriado porque é um "índice de cobertura", a consulta pode ser satisfeita inteiramente a partir do índice sem fazer referência a páginas de dados na tabela subjacente, e há um predicado de igualdade na coluna inicial e um ORDER BY nas próximas duas colunas, de modo que evitará uma operação de "classificação".

--

Se você tem a garantia de que o type_code ou name coluna na tabela itpitnam NÃO é NULL, você pode adicionar um predicado para eliminar as linhas que estão "faltando" uma linha correspondente, por exemplo
HAVING artist IS NOT NULL

(Adicionar isso provavelmente terá um impacto no desempenho.) Na ausência desse tipo de garantia, você precisaria adicionar um INNER JOIN ou um predicado que testasse a existência de uma linha correspondente, para obter um comportamento INNER JOIN.