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

Jak korzystać z ORDER BY wewnątrz UNION

Coś takiego powinno działać w MySQL:

SELECT a.*
  FROM ( 
         SELECT ...  FROM ... ORDER BY ... 
       ) a
 UNION ALL 
SELECT b.*
  FROM ( 
         SELECT ...  FROM ... ORDER BY ... 
       ) b

zwracać wiersze w kolejności, w jakiej chcielibyśmy, aby zostały zwrócone. np. MySQL wydaje się honorować ORDER BY klauzule wewnątrz widoków wbudowanych.

Ale bez ORDER BY klauzuli w najbardziej zewnętrznym zapytaniu, kolejność, w jakiej wiersze są zwracane, jest nie gwarantowane.

Jeśli potrzebujemy wierszy zwracanych w określonej sekwencji, możemy dołączyć ORDER BY w zapytaniu zewnętrznym. W wielu przypadkach możemy po prostu użyć ORDER BY na najbardziej zewnętrznym zapytaniu, aby spełnić wyniki.

Ale kiedy mamy przypadek użycia, w którym potrzebujemy wszystkich wierszy z pierwszego zapytania zwróconych przed wszystkimi wierszami z drugiego zapytania, jedną z opcji jest uwzględnienie dodatkowej kolumny dyskryminującej w każdym z zapytań. Na przykład dodaj ,'a' AS src w pierwszym zapytaniu, ,'b' AS src do drugiego zapytania.

Wtedy najbardziej zewnętrzne zapytanie może zawierać ORDER BY src, name , aby zagwarantować kolejność wyników.

KONTYNUACJA

W pierwotnym zapytaniu ORDER BY w zapytaniach jest odrzucany przez optymalizator; ponieważ nie ma ORDER BY zastosowane do zapytania zewnętrznego, MySQL może zwracać wiersze w dowolnej kolejności.

"Sztuczka" w zapytaniu w mojej odpowiedzi (powyżej) zależy od zachowania, które może być specyficzne dla niektórych wersji MySQL.

Przypadek testowy:

wypełnij tabele

CREATE TABLE foo2 (id INT PRIMARY KEY, role VARCHAR(20)) ENGINE=InnoDB;
CREATE TABLE foo3 (id INT PRIMARY KEY, role VARCHAR(20)) ENGINE=InnoDB;

INSERT INTO foo2 (id, role) VALUES 
  (1,'sam'),(2,'frodo'),(3,'aragorn'),(4,'pippin'),(5,'gandalf');
INSERT INTO foo3 (id, role) VALUES 
  (1,'gimli'),(2,'boromir'),(3,'elron'),(4,'merry'),(5,'legolas');

zapytanie

SELECT a.*
  FROM ( SELECT s.id, s.role
           FROM foo2 s
          ORDER BY s.role
       ) a
 UNION ALL
SELECT b.*
  FROM ( SELECT t.id, t.role
           FROM foo3 t
          ORDER BY t.role
       ) b

zwrócono zestaw wyników

    id  role     
 ------  ---------
      3  aragorn  
      2  frodo    
      5  gandalf  
      4  pippin   
      1  sam      
      2  boromir  
      3  elron    
      1  gimli    
      5  legolas  
      4  merry    

Wiersze z foo2 zwracane są "w kolejności", po których następują wiersze z foo3 , ponownie „w kolejności”.

Pamiętaj (ponownie), że to zachowanie NIE gwarantowane. (Zachowanie, które obserwujemy, jest efektem ubocznym tego, jak MySQL przetwarza widoki wbudowane (tabele pochodne). To zachowanie może być inne w wersjach po 5.5.)

Jeśli potrzebujesz wierszy zwróconych w określonej kolejności, określ ORDER BY klauzula dla najbardziej zewnętrznego zapytania. A ta kolejność będzie dotyczyć całej zestaw wyników.

Jak wspomniałem wcześniej, gdybym najpierw potrzebował wierszy z pierwszego zapytania, a następnie z drugiego, do każdego zapytania dołączyłbym kolumnę „dyskryminator”, a następnie do klauzuli ORDER BY dołączyłem kolumnę „dyskryminator”. Zrezygnowałbym również z widoków wbudowanych i zrobiłby coś takiego:

SELECT s.id, s.role, 's' AS src
  FROM foo2 s
 UNION ALL
SELECT t.id, t.role, 't' AS src
  FROM foo3 t
 ORDER BY src, role


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Doctrine nie utrwala encji z wartościami boolowskimi i PDO::ATTR_EMULATE_PREPARES =false w Mysql

  2. Liczenie wszystkich postów należących do kategorii ORAZ jej podkategorii

  3. Typ danych wyniku SUM w MySQL

  4. mysql-connector-java-8.0.12 :pojawia się błąd dla strefy czasowej serwera „Czas standardowy półwyspu malajskiego”

  5. Wyzwalacz MySQL do sprawdzania wartości przed wstawieniem wielu razy