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

SQL UNION ALL, aby wyeliminować duplikaty

Ale w tym przykładzie pierwsze zapytanie ma warunek w kolumnie a , podczas gdy drugie zapytanie ma warunek w kolumnie b . Prawdopodobnie pochodzi z zapytania, które trudno zoptymalizować:

SELECT * FROM mytable WHERE a=X OR b=Y

To zapytanie jest trudne do zoptymalizowania za pomocą prostego indeksowania B-drzewa. Czy wyszukiwarka przeszukuje indeks w kolumnie a? ? Lub w kolumnie b ? Tak czy inaczej, wyszukiwanie drugiego terminu wymaga skanowania tabeli.

Stąd sztuczka polegająca na użyciu UNION do rozdzielenia na dwa zapytania dla każdego terminu. Każde podzapytanie może używać najlepszego indeksu dla każdego wyszukiwanego terminu. Następnie połącz wyniki za pomocą UNION.

Ale te dwa podzbiory mogą się nakładać, ponieważ w niektórych wierszach b=Y może również mieć a=X w takim przypadku takie wiersze występują w obu podzbiorach. Dlatego musisz powtórzyć eliminację, w przeciwnym razie kilka wierszy zostanie wyświetlonych dwukrotnie w wyniku końcowym.

SELECT * FROM mytable WHERE a=X 
UNION DISTINCT
SELECT * FROM mytable WHERE b=Y

UNION DISTINCT jest drogie, ponieważ typowe implementacje sortują wiersze w celu znalezienia duplikatów. Tak jak w przypadku użycia SELECT DISTINCT ... .

Mamy również wrażenie, że jest to jeszcze bardziej „zmarnowana” praca, jeśli dwa podzbiory wierszy, które łączysz, mają wiele wierszy występujących w obu podzbiorach. Trzeba wyeliminować wiele wierszy.

Ale nie ma potrzeby eliminowania duplikatów, jeśli możesz zagwarantować, że dwa zestawy wierszy są już różne. Oznacza to, że jeśli gwarantujesz, że nie ma nakładania się. Jeśli możesz na tym polegać, wyeliminowanie duplikatów zawsze byłoby niemożliwe, a zatem zapytanie może pominąć ten krok, a tym samym pominąć kosztowne sortowanie.

Jeśli zmienisz zapytania, aby zagwarantować, że będą wybierały nienakładające się podzbiory wierszy, jest to wygrana.

SELECT * FROM mytable WHERE a=X 
UNION ALL 
SELECT * FROM mytable WHERE b=Y AND a!=X

Gwarantujemy, że te dwa zestawy nie będą się pokrywać. Jeśli pierwszy zestaw zawiera wiersze, w których a=X a drugi zestaw ma wiersze, w których a!=X wtedy nie może być żadnego wiersza, który znajduje się w obu zestawach.

Dlatego drugie zapytanie wyłapuje tylko niektóre wierszy, w których b=Y , ale dowolny wiersz, w którym a=X AND b=Y jest już zawarty w pierwszym zestawie.

Zatem zapytanie osiąga zoptymalizowane wyszukiwanie dla dwóch OR terminów, bez tworzenia duplikatów i niewymagających UNION DISTINCT operacja.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Znajdowanie wszystkich rodziców w tabeli mysql za pomocą pojedynczego zapytania (zapytanie rekurencyjne)

  2. mysql przechowywana-procedura:out parametr

  3. różnica między where_in i find_in_set

  4. Dołącz do nas w Amsterdamie na spotkanie z OptimaData i vidaXL

  5. Użyj powiązanego parametru wiele razy