Mysql
 sql >> база данни >  >> RDS >> Mysql

Как да използвате ORDER BY вътре в UNION

Нещо подобно трябва да работи в MySQL:

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

за връщане на редове в реда, в който бихме искали да бъдат върнати. т.е. MySQL изглежда спазва ORDER BY клаузи във вградените изгледи.

Но без ORDER BY клауза на най-външната заявка, редът, в който се връщат редовете, е не гарантирано.

Ако имаме нужда от редовете, върнати в определена последователност, можем да включим ORDER BY на най-външната заявка. В много случаи на употреба можем просто да използваме ORDER BY на най-външната заявка, за да задоволи резултатите.

Но когато имаме случай на използване, при който се нуждаем от всички редове от първата заявка, върнати преди всички редове от втората заявка, една от опциите е да включим допълнителна колона с дискриминатор във всяка от заявките. Например добавете ,'a' AS src в първата заявка, ,'b' AS src към втората заявка.

Тогава най-външната заявка може да включва ORDER BY src, name , за да се гарантира последователността на резултатите.

ПОСЛЕДВАНЕ

В оригиналната ви заявка ORDER BY във вашите заявки се отхвърля от оптимизатора; тъй като няма ORDER BY приложен към външната заявка, MySQL е свободен да връща редовете в какъвто ред иска.

„Трикът“ в заявката в моя отговор (по-горе) зависи от поведението, което може да е специфично за някои версии на MySQL.

Тестов случай:

попълване на таблици

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');

заявка

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

върнати резултати

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

Редовете от foo2 се връщат "в ред", последвани от редовете от foo3 , отново "по ред".

Обърнете внимание (отново), че това поведение е НЕ гарантирано. (Поведението, което наблюдаваме, е страничен ефект от това как MySQL обработва вградени изгледи (извлечени таблици). Това поведение може да е различно във версии след 5.5.)

Ако имате нужда от връщане на редовете в определен ред, посочете ORDER BY клауза за най-външната заявка. И това подреждане ще важи за цялото набор от резултати.

Както споменах по-рано, ако имам нужда първо от редовете от първата заявка, последвана от втората заявка, ще включа колона "дискриминатор" във всяка заявка и след това ще включа колоната "дискриминатор" в клаузата ORDER BY. Също така бих премахнал вградените изгледи и бих направил нещо подобно:

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. PHP - MySQL заявка с разделяне на страници

  2. Може ли една таблица да има два външни ключа?

  3. Конфигурирайте пул за връзки на GlassFish JDBC, за да управлявате превключване на Amazon RDS Multi-AZ

  4. Идентификатор на ресурс #4 PHP MYSQL

  5. разбирането на mysql обяснява