Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Die Verwendung von DISTINCT innerhalb von JOIN verursacht Probleme

Ein Ansatz besteht darin, eine Inline-Ansicht zu verwenden, wie die Abfrage, die Sie bereits haben. Aber anstatt DISTINCT zu verwenden, würden Sie ein GROUP BY verwenden, um Duplikate zu eliminieren. Die einfachste Inline-Ansicht zur Erfüllung Ihrer Anforderungen wäre:

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

Obwohl es nicht deterministisch ist, aus welcher Zeile von itpitnam die Werte für name und type_code abgerufen werden. Eine ausgefeiltere Inline-Ansicht kann dies spezifischer machen.

Ein weiterer gängiger Ansatz für diese Art von Problem ist die Verwendung einer korrelierten Unterabfrage in der SELECT-Liste. Für die Rückgabe eines kleinen Satzes von Zeilen kann dies recht gut funktionieren. Aber für die Rückgabe großer Sätze gibt es effizientere Ansätze.

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

Diese Abfrage gibt das angegebene Resultset mit einem signifikanten Unterschied zurück. Die ursprüngliche Abfrage zeigt einen INNER JOIN zu itpitnam Tisch. Das bedeutet, dass NUR eine Zeile zurückgegeben wird, wenn es eine passende Zeile in itpitnam gibt Tisch. Die obige Abfrage emuliert jedoch einen OUTER JOIN, die Abfrage gibt eine Zeile zurück, wenn keine übereinstimmende Zeile in itpitnam gefunden wird .

AKTUALISIEREN

Für die beste Leistung dieser korrelierten Unterabfragen benötigen Sie einen geeigneten verfügbaren Index,

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

Dieser Index ist am besten geeignet, da es sich um einen "abdeckenden Index" handelt, die Abfrage vollständig aus dem Index ausgeführt werden kann, ohne auf Datenseiten in der zugrunde liegenden Tabelle zu verweisen, und es ein Gleichheitsprädikat für die führende Spalte und ein ORDER BY für die nächsten beiden Spalten gibt. damit wird eine "Sortieren"-Operation vermieden.

--

Wenn Sie eine Garantie haben, dass entweder der type_code oder name Spalte in der itpitnam-Tabelle NICHT NULL ist, können Sie ein Prädikat hinzufügen, um die Zeilen zu eliminieren, denen eine passende Zeile "fehlt", z. B.

HAVING artist IS NOT NULL

(Das Hinzufügen wird sich wahrscheinlich auf die Leistung auswirken.) Ohne diese Art von Garantie müssten Sie einen INNER JOIN oder ein Prädikat hinzufügen, das auf das Vorhandensein einer übereinstimmenden Zeile testet, um ein INNER JOIN-Verhalten zu erhalten.