2012-08-10 11 views
8

Ben postgres aşağıdaki sorgu:Garip sipariş hata (bir hata olduğunu?) Postgres'e özdeş değerlere sahip iki sütun sipariş verirken

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

için özdeş bir session_time vardır 21. kayıt.

Bu sorgu, 20 sonuç döndürür, ancak sonuçları tüm veritabanıyla karşılaştırırsanız, sorgu 1.-19. Sonuçları ve 21.sünü atlayarak 20'yi döndürür.

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

Ancak bu böcek olarak nasıl gerçekleştiğini merak:

Bu sorgu

düzene, "id" ekleyerek düzeltilebilir? Postgres, ofset ve limitleri kullanırken aynı siparişi nasıl verir? Rastgele mi? Postgres ile bir hata mı?

+4

Belirleyici sonuçlar istiyorsanız, siparişinize göre benzersiz bir kravat kırıcı eklemeniz gerekir. Bu, hiçbir "emri" içermemekle ve sonuçları belirli bir sıraya göre sıralamakla beklemekle aynı şeydir. Yapacaklarına dair bir garanti yok. –

+3

Neye atıfta bulunduğunuza istikrarlı bir sıralama denir. Sabit bir sıralama, eşleşen anahtarlara sahip olduklarında kayıtları orijinal sırada tutar. SQL'de kararlı bir sıralama için kesinlikle gerek yoktur. Herhangi bir üründe buna bağlı olmayacağım. Martin'in de belirttiği gibi, başka bir sütunu bir kravat kırıcı olarak kullanın. –

+6

Bu kesinlikle bir * bir hata - sadece 'session_time' tarafından sipariş için sordu ve planlayıcısı size bunu yapan en hızlı planı verecek; Ne belirmediysen sipariş etmek isteyebileceğin * başka * hakkında hiçbir varsayımda bulunmaz. Sadece eğlenmek için, bu satırlardan birini (mevcut değerlere bile) güncelleyin ve 'ORDER BY' deyişi olmadan' SELECT 'yapın. Belirli bir sıradaki şeyleri istiyorsanız, bunu belirtmeniz gerekir. – kgrittn

cevap

8

Bu bir hata değil. Limit ve ofset, sipariş verildikten sonra gerçekleşir ve bir satırdaki diğerine göre hangi sıraların seçildiği deterministik değildir. Genel olarak, siparişinizin istikrarlı ve deterministik olması için bir talihliye sahip olmak istersiniz (sorguyu her çalıştırıldığında aynı olduğundan emin olmak için limit veya ofset sorunum olmasa bile benzersiz tiebreaker kullanmayı tercih ederim).

Sayfalandırma yapıyorsanız, birincil anahtarı veya vekil anahtarını sıralı olarak sıraya ekleyin. Bu gerçekten en iyi yoldur.