sql >> Database >  >> RDS >> Mysql

Het gebruik van DISTINCT binnen JOIN zorgt voor problemen

Een benadering is om een ​​inline-weergave te gebruiken, zoals de query die u al heeft. Maar in plaats van DISTINCT te gebruiken, zou u een GROUP BY gebruiken om duplicaten te elimineren. De eenvoudigste inline-weergave om aan uw vereisten te voldoen, is:

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

Hoewel het niet deterministisch is van welke rij uit itpitnam de waarden voor naam en type_code worden opgehaald. Een uitgebreidere inline-weergave kan dit specifieker maken.

Een andere veelvoorkomende benadering van dit type probleem is het gebruik van een gecorreleerde subquery in de SELECT-lijst. Voor het retourneren van een kleine set rijen kan dit redelijk goed presteren. Maar voor het retourneren van grote sets zijn er efficiëntere benaderingen.

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

Die query retourneert de opgegeven resultatenset, met één significant verschil. De originele zoekopdracht toont een INNER JOIN naar de itpitnam tafel. Dat betekent dat er ALLEEN een rij wordt geretourneerd als er een overeenkomende rij is in de itpitnam tafel. De bovenstaande query emuleert echter een OUTER JOIN, de query retourneert een rij wanneer er geen overeenkomende rij is gevonden in itpitnam .

UPDATE

Voor de beste prestaties van die gecorreleerde subquery's, moet u een geschikte index beschikbaar hebben,

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

Die index is het meest geschikt omdat het een "bedekkende index" is, de zoekopdracht kan volledig vanuit de index worden uitgevoerd zonder te verwijzen naar gegevenspagina's in de onderliggende tabel, en er is een gelijkheidspredikaat op de eerste kolom en een ORDER BY op de volgende twee kolommen, zodat een "sorteer" -bewerking wordt vermeden.

--

Als u de garantie heeft dat ofwel de type_code of name kolom in de itpitnam-tabel is NIET NULL, u kunt een predikaat toevoegen om de rijen te elimineren die een overeenkomende rij "ontbreken", bijv.

HAVING artist IS NOT NULL

(Als u dat toevoegt, heeft dit waarschijnlijk invloed op de prestaties.) Zonder dat soort garantie moet u een INNER JOIN toevoegen of een predikaat dat test op het bestaan ​​van een overeenkomende rij, om een ​​INNER JOIN-gedrag te krijgen.



  1. Hoe maak je een 'juiste case'-opmaak van een mysql-kolom?

  2. SQL-query om het aantal wederzijdse vrienden te vinden, gegeven een tabel met persoon, vriendenpaar

  3. Wat is gebruikersnaam/wachtwoord voor verbinding in MySQL-workbench?

  4. Het proces van synchronisatie van SQL Server-databaseschema's automatiseren