Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Używanie DISTINCT w JOIN powoduje problemy

Jednym ze sposobów jest użycie widoku wbudowanego, takiego jak zapytanie, które już masz. Ale zamiast używać DISTINCT, użyjesz GROUP BY, aby wyeliminować duplikaty. Najprostszy widok wbudowany spełniający Twoje wymagania to:

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

Chociaż nie jest to deterministyczne, z którego wiersza z itpitnam są pobierane wartości name i type_code. Bardziej rozbudowany widok wbudowany może sprawić, że będzie to bardziej szczegółowe.

Innym powszechnym podejściem do tego typu problemu jest użycie skorelowanego podzapytania na liście SELECT. W przypadku zwracania małego zestawu wierszy może to działać dość dobrze. Ale w przypadku zwracania dużych zestawów istnieją bardziej wydajne podejścia.

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

To zapytanie zwróci określony zestaw wyników z jedną istotną różnicą. Oryginalne zapytanie pokazuje INNER JOIN do itpitnam stół. Oznacza to, że wiersz zostanie zwrócony TYLKO z pasującego wiersza w itpitnam stół. Powyższe zapytanie emuluje jednak OUTER JOIN, zapytanie zwróci wiersz, gdy nie zostanie znaleziony pasujący wiersz w itpitnam .

AKTUALIZACJA

Aby uzyskać najlepszą wydajność tych skorelowanych podzapytań, potrzebny będzie odpowiedni indeks,

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

Ten indeks jest najbardziej odpowiedni, ponieważ jest to „indeks pokrywający”, zapytanie może być wykonane w całości z indeksu bez odwoływania się do stron danych w tabeli bazowej, a w kolumnie wiodącej występuje predykat równości, a w kolejnych dwóch kolumnach ORDER BY. dzięki czemu unikniemy operacji sortowania.

--

Jeśli masz gwarancję, że type_code lub name kolumna w tabeli itpitnam NIE JEST NULL, możesz dodać predykat, aby wyeliminować wiersze, w których „brakuje” pasującego wiersza, np.

HAVING artist IS NOT NULL

(Dodanie tego prawdopodobnie będzie miało wpływ na wydajność.) W przypadku braku tego rodzaju gwarancji należałoby dodać INNER JOIN lub predykat sprawdzający istnienie pasującego wiersza, aby uzyskać zachowanie INNER JOIN.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL, zwróć wszystkie wyniki w ciągu X ostatnich godzin

  2. Spring Mvc Hibernate Encoding/Multi-line import sql

  3. Problem z kodowaniem PDO UTF-8?

  4. jaki jest sens serializacji tablic, aby przechowywać je w bazie danych?

  5. zapisz wyniki zapytania sql do pliku w mysql