Mysql
 sql >> Database >  >> RDS >> Mysql

L'uso di DISTINCT all'interno di JOIN sta creando problemi

Un approccio consiste nell'usare una vista in linea, come la query che hai già. Ma invece di usare DISTINCT, useresti un GROUP BY per eliminare i duplicati. La visualizzazione in linea più semplice per soddisfare le tue esigenze sarebbe:

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

Sebbene non sia deterministico su quale riga da itpitnam vengono recuperati i valori per name e type_code. Una visualizzazione in linea più elaborata può renderlo più specifico.

Un altro approccio comune a questo tipo di problema consiste nell'utilizzare una sottoquery correlata nell'elenco SELECT. Per restituire una piccola serie di righe, questo può funzionare abbastanza bene. Ma per restituire grandi set, ci sono approcci più efficienti.

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

Tale query restituirà il set di risultati specificato, con una differenza significativa. La query originale mostra un INNER JOIN al itpitnam tavolo. Ciò significa che verrà restituita una riga SOLO se esiste una riga corrispondente nel itpitnam tavolo. La query sopra, tuttavia, emula un OUTER JOIN, la query restituirà una riga quando non è stata trovata alcuna riga corrispondente in itpitnam .

AGGIORNAMENTO

Per ottenere le migliori prestazioni di quelle sottoquery correlate, ti consigliamo di disporre di un indice appropriato,

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

Quell'indice è più appropriato perché è un "indice di copertura", la query può essere soddisfatta interamente dall'indice senza fare riferimento alle pagine di dati nella tabella sottostante e c'è un predicato di uguaglianza nella colonna iniziale e un ORDER BY nelle due colonne successive, in modo che eviterà un'operazione di "ordinamento".

--

Se hai una garanzia che il type_code o name la colonna nella tabella itpitnam NON è NULL, puoi aggiungere un predicato per eliminare le righe che "mancano" una riga corrispondente, ad es.

HAVING artist IS NOT NULL

(L'aggiunta di ciò avrà probabilmente un impatto sulle prestazioni.) In assenza di questo tipo di garanzia, dovresti aggiungere un INNER JOIN o un predicato che verifica l'esistenza di una riga corrispondente, per ottenere un comportamento INNER JOIN.