sql >> Databáze >  >> RDS >> Mysql

Použití DISTINCT uvnitř JOIN způsobuje potíže

Jedním z přístupů je použití inline zobrazení, jako je dotaz, který již máte. Ale místo použití DISTINCT byste k odstranění duplikátů použili GROUP BY. Nejjednodušší vložený pohled pro splnění vašich požadavků by byl:

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

Ačkoli to není deterministické, pokud jde o to, ze kterého řádku z itpitnam jsou načteny hodnoty pro name a type_code. Propracovanější inline zobrazení to může upřesnit.

Dalším běžným přístupem k tomuto typu problému je použití korelovaného poddotazu v seznamu SELECT. Pro vrácení malé sady řádků to může fungovat poměrně dobře. Ale pro vracení velkých souborů existují efektivnější přístupy.

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

Tento dotaz vrátí zadanou sadu výsledků s jedním významným rozdílem. Původní dotaz ukazuje INNER JOIN k itpitnam stůl. To znamená, že řádek bude vrácen POUZE v případě, že v itpitnam existuje odpovídající řádek stůl. Výše uvedený dotaz však emuluje OUTER JOIN, dotaz vrátí řádek, pokud v itpitnam nebude nalezen žádný odpovídající řádek .

AKTUALIZACE

Pro nejlepší výkon těchto korelovaných poddotazů budete chtít mít k dispozici vhodný index,

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

Tento index je nejvhodnější, protože je to „krycí index“, dotaz lze uspokojit zcela z indexu bez odkazování na datové stránky v podkladové tabulce a v úvodním sloupci je predikát rovnosti a v dalších dvou sloupcích je ORDER BY, takže se vyhnete operaci "třídění".

--

Pokud máte záruku, že buď type_code nebo name sloupec v tabulce itpitnam NENÍ NULL, můžete přidat predikát, abyste odstranili řádky, kterým „chybí“ odpovídající řádek, např.

HAVING artist IS NOT NULL

(Přidání bude mít pravděpodobně dopad na výkon.) Bez této záruky byste museli přidat INNER JOIN nebo predikát, který testuje existenci shodného řádku, abyste získali chování INNER JOIN.



  1. ukládání čísel jako varchar

  2. Může mysql importovat csv nebo jiný soubor txt do jednoho sloupce?

  3. jak vybrat pouze řádek s maximální sekvencí bez použití poddotazu?

  4. Proč a kdy LEFT JOIN s podmínkou v klauzuli WHERE není ekvivalentní stejnému LEFT JOIN v ON?