2012-08-10 6 views
8

Ho la seguente query in postgres:strano ordinamento insetto (è un baco?) In postgres momento dell'ordine due colonne con valori identici

SELECT * 
FROM "bookings" 
WHERE ("bookings".client_id = 50) 
ORDER BY session_time DESC 
LIMIT 20 OFFSET 0 

Il record nel 20 posto è ha un session_time identico 21 ° record.

Questa query restituisce 20 risultati, tuttavia se si confrontano i risultati con l'intero database, la query restituisce i risultati dal 1 ° al 19 ° e il 21 °, saltando oltre il 20 °.

Questa query può essere risolto con l'aggiunta, "ID" per l'ordine:

SELECT * 
FROM "bookings" 
WHERE ("bookings".client_id = 50) 
ORDER BY session_time DESC, id 
LIMIT 20 OFFSET 0 

Tuttavia mi chiedevo come si è verificato questo bug? In che modo Postgres ordina file identici quando utilizza offset e limiti? È casuale? È un bug con postgres?

+4

Se si desidera ottenere risultati deterministici, è necessario includere un unico tie breaker nel proprio ordine entro. È come non avere "ordine per" e aspettarsi che i risultati siano ordinati in un ordine particolare. Non garantisce che lo faranno. –

+3

Ciò a cui si fa riferimento è chiamato ordinamento stabile. Un ordinamento stabile conserva i record nell'ordine originale quando dispongono di chiavi corrispondenti. Non c'è sicuramente alcun requisito per un ordinamento stabile in SQL. Non ne dipenderei in nessun prodotto. Come suggerisce Martin, usa un'altra colonna come un tie breaker. –

+6

Questo è sicuramente * non * un bug - lo hai richiesto solo ordinato da 'session_time', e il planner ti darà il piano più veloce che lo faccia; non fa supposizioni su ciò che * altrimenti * potresti voler ordinare con quello che non hai indicato. Solo per divertimento, aggiorna una di queste righe (anche ai valori correnti) e fai un 'SELECT' senza una clausola' ORDER BY'. Se vuoi le cose in un ordine particolare, devi specificarlo. – kgrittn

risposta

8

Questo non è un bug. Il limite e l'offset si verificano dopo l'ordine e non è deterministico quali righe siano selezionate in un caso o in un altro. In generale, si desidera avere un tie-breaker in modo che il tuo ordine sia stabile e deterministico (preferisco utilizzare tiebreaker unici anche quando non ho problemi di limiti o offset per garantire che la query sia la stessa ogni volta che viene eseguita).

Se si sta eseguendo l'impaginazione, aggiungere la chiave primaria o la chiave surrogata all'ordinamento come un tie-break. Questo è davvero il modo migliore.