2013-04-27 11 views
6

Zastanawiam się w szczególności nad PostgreSQL. Biorąc pod uwagę następujące wymyślony przykład:Czy porządek w podzapytaniu jest gwarantowany?

SELECT name FROM 
    (SELECT name FROM people WHERE age >= 18 ORDER BY age DESC) p 
LIMIT 10 

są imiona wrócił z zewnętrznej kwerendy gwarantowanej się być w kolejności ich dla zapytania wewnętrznej?

+4

Ze względu na optymalizację, to pewnie by zwrócić je w porządku ... ale zgodnie ze standardem SQL, kolejność pod-zapytanie nie wpływa na główne zapytanie. – Godeke

Odpowiedz

9

Nie umieścić zamówienie w zapytaniu zewnętrzna:

SELECT name FROM 
    (SELECT name, age FROM people WHERE age >= 18) p 
ORDER BY p.age DESC 
LIMIT 10 

wewnętrznej (pod) zwraca wynik zapytania-zestawu. Jeśli złożysz zamówienie tam, wówczas pośredni zestaw wyników przekazany z zapytania wewnętrznego (pod), do kwerendy zewnętrznej, jest gwarantowany, że zostanie uporządkowany zgodnie z tym, co wybierzesz, ale bez kolejności w zapytaniu zewnętrznym, wynik -set wygenerowany przez przetwarzanie tego wewnętrznego zestawu wyników zapytania, nie ma gwarancji, że zostanie posortowany w jakikolwiek sposób.

+0

Co do cholery ?! Jeśli nie chce tego zrobić, dlaczego nie po prostu podać błąd składni? – Adamantish

+0

Zapytanie wewnętrzne (pod) zwraca zestaw wyników. Jeśli umieścisz tam zlecenie, wówczas wynik pośredni przekazany z zapytania wewnętrznego (pod), do zapytania zewnętrznego, jest gwarantowany, że zostanie uporządkowany w sposób wyznaczony, ale zestaw wyników wygenerowany przez zapytanie zewnętrzne, poprzez przetworzenie tego zapytania wewnętrznego zestaw wyników, nie jest. –

+0

Interesujący subtelny punkt. Domyślam się, że kolejność uporządkowanych zestawów wyników nie zmieni się, dopóki nie połączę się z drugim zestawem wyników, ale zobaczę, jak trudne może być odgadnięcie optymalizatora. – Adamantish

0

Nie można zagwarantować, że będzie w tej samej kolejności, ale po uruchomieniu może się okazać, że generalnie następuje kolejność.

Należy złożyć zamówienie przez w głównym zapytaniu

SELECT name FROM 
(SELECT name FROM people WHERE age >= 18) p 
ORDER BY p.age DESC LIMIT 10 
4

W prostych przypadkach @Charles query jest najbardziej efektywne.

Bardziej ogólnie, można użyć funkcji okna row_number() nosić dowolny kolejność chcesz głównym zapytaniu, w tym:

  • zamówienie kolumnami nie na liście SELECT podzapytania, a tym samym nie można odtwarzać
  • arbitralne zamówienie rówieśników według kryteriów ORDER BY. Postgres użyje ponownie tej samej dowolnej kolejności w funkcji okna w podzapytaniu w ramach. (Ale nie na przykład prawdziwie losowa kolejność od random() na przykład!)
    Jeśli nie chcesz zachować arbitralnej kolejności sortowania elementów równorzędnych z podzapytania, użyj zamiast tego wartości rank().

To może być także ogólnie lepszy złożonych zapytań lub wieloma warstwami zapytanie:

SELECT name 
FROM (
    SELECT name, row_number OVER (ORDER BY <same order by criteria>) AS rn 
    FROM people 
    WHERE age >= 18 
    ORDER BY <any order by criteria> 
    ) p 
ORDER BY p.rn 
LIMIT 10; 
Powiązane problemy