2009-03-23 10 views
5

MySQLTek bir kaydın * konumunu *, sınırlı, isteğe göre sıralanmış bir kayıt kümesinde nasıl bulabilirsiniz?

bazı id ile sadece tek bir kayıt almak istediğinizi varsayalım, ama sen büyük bir sipariş Seti içinde karşılaşılan olsaydın konumunu olurdu bilmek istiyorum. noktasında

Vaka fotoğraf galerisi. Tek bir fotoğrafa inersiniz, ancak sistemin tüm galeride ofsetinin ne olduğunu bilmesi gerekir.

Ben pozisyonların takip etmek için özel indeksleme alanları kullanabilirsiniz, ancak tek başına SQL daha zarif bir yolu olmalı herhalde.

+0

Bunu yapmanın hiçbir ANSI yolu yok. Hangi DB sunucusunu kullandığınızı söyleyebilirseniz, yardımcı olabiliriz. Eklemek için sorunuzu düzenleyin. – Seb

+0

Ah evet .. MySQL .. üzgünüm unuttum o bit –

+0

Bunu neden yapmak istiyorsun? Biraz netleştirin - çünkü önceki ve sonraki fotoğrafları gösterecek pozisyonu bilmeniz gerekmiyor ... vb. –

cevap

2

Bu nedenle, ilk olarak, ORDER BY öğeniz ne olursa olsun, sırayla # olan bir sanal tablo oluşturursunuz, o zaman bu setten en yüksek olanı seçersiniz. Daha büyük sonuç kümesindeki pozisyon budur. Benzersiz bir değer/set değeriyle sipariş vermemeniz halinde sorun yaşarsınız ...

(photo_gallery_id, date_created_on) üzerinde bir dizin oluşturursanız, indeks taraması yapabilir (fotoğrafların dağıtımına bağlı olarak)), bir tablo taramasından daha hızlı olması gerekir (gallery_id'iniz fotoğrafların% 90'ını veya neyi içermediyse).

SELECT @row := 0; 
SELECT MAX(position) 
    FROM (SELECT @row := @row + 1 AS position 
      FROM photos 
      WHERE photo_gallery_id = 43 
      AND date_created_on <= 'the-date-time-your-photo-was' 
      ORDER BY date_created_on) positions; 
+0

Bu sanal tablo tekniğini bilmiyordum .. teşekkürler –

0

Gerçekten değil. Bence Oracle sana bir "ROWID" ya da bunun gibi bir şey veriyor, ama çoğu size bir şey vermiyor. Veritabanınızdaki girişin galeride konumlanmasını istediğinizi söyleyen bir sütun gibi özel bir sipariş, SQL'in içinde olması gerektiğini düşündüğünüz sırayla masaya bir şeyler koyacağından asla emin olamazsınız.

0

Eğer SQL Server 2005'te, kullanmakta olduğunuz veritabanı hakkında özgü değildir gibi sen

SELECT 
    ROW_NUMBER() OVER (ORDER BY PhotoID) 
    , PhotoID 
FROM dbo.Photos 
0

kullandığınız hangi DBMS söyleme kullanabilir ve "çözüm" buna göre değişecektir. Oracle size bu yapabilirdi (ama sizi değil çağırıyorum!):

select photo, offset 
from 
(select photo 
    ,  row_number() over (partition by gallery_id, order by photo_seq) as offset 
    from photos 
) 
where id = 123 

Tüm fotoğrafları (tam tablo taraması) seçin ve ardından istedi olanları ayırt edecek O sorgusu - değil Bir performans sorusu! Eğer gerçekten saklanmalıdır bu bilgilere gerekiyorsa

öneririm. kimliğe göre yalnızca belirlenir görev üstlenen

0

, emin değilim daha küçük bir id değeri ?:

select 
    po.[id] 
    ... 
    ((select count(pi.[id]) from photos pi where pi.[id] < po.[id]) + 1) as index 
    ... 
from photos po 
... 

ile tüm kayıtları sayma kadar basit değil ne tür bir performans etkileri sorgu olurdu, ama çok fazla kayıt döndürmenin bir sorun olabileceğini düşünürdüm.

+0

Hayır, sıralama keyfi. –

0

bir "uygulama anahtar" ve "teknik anahtar" arasındaki farkı anlamak gerekir.

teknik anahtar bir öğe benzersiz yapmak için tek amacı vardır. Genellikle INTEGER veya BIGINT, oluşturulan (kimlik, her neyse). Bu anahtar, veritabanındaki nesneleri bulmak için kullanılır, bir nesneyi çabucak anlamaya devam eder (ID'lerin> 0 olması gerekir, yani varsayılan ID == 0 olan bir nesne henüz DB'de değil), vb.

uygulama tuşu başvurunuzun kapsamında bir nesnenin mantıklı gereken bir şeydir. Bu durumda, galerideki fotoğrafların sırası. Bunun veritabanı için hiçbir anlamı yoktur.

Sipariş listesi düşün: Bu, çoğu dilde varsayılan değerdir. Bir dizinin eriştiği bir dizi öğeniz var. Bir veritabanı için, bu dizin bir uygulama anahtarıdır, çünkü veritabanındaki kümeler sırasızdır (veya SİPARİŞ BY) belirtmedikçe veritabanı herhangi bir sipariş vermez. Aynı nedenden ötürü, bir sorgudan gelen sonuçlara çağrı yapmak bir acıdır: Veritabanları gerçekten “konum” fikrini sevmezler.

Yapmanız gereken şey, bir dizin satırı eklemektir (örn. Galerinizde hangi konumda olduğunu gösteren bir INTEGER, bu sütunda bir dizin oluşturmanıza rağmen daha hızlı erişim için bir veritabanı dizini değildir). .) ve bunu koru. Her ekleme için, UPDATE index = index + 1 where index >= insertion_point, vb.

Evet, bu berbat. Tek bildiğim çözüm: Bunu sizin için çözen bir ORM çerçevesi kullanın.

+0

Tamam, bu nedenle özel bir endeks sürdürmek önerdiğiniz şeydir. Söylediğin gibi yapar. Özellikle bu endeksi yenilemek için olası siparişlerden biri olarak sık sık yapılması gerekir. Kullanıcı oyları –

+0

Unutmayın: Sadece bir teknik anahtara sahip olabilirsiniz (genellikle birincil anahtar) ancak birçok uygulama anahtarınız olabilir (ve ORDER BY komutunu kullanabilirsiniz). onlara göre sırala). Böylece bu sıralama bir RATING sütununa sahip olarak uygulayabilirsiniz. –

0

Ekstra bir tabloya gerek yok, neden sadece kayıtları değil?

Görüntülendikleri sıralamayı biliyorsunuz (hangisi değişebilir), ama biliyorsunuz.

Ayrıca, geçerli kaydın kimliğini de biliyorsunuz; tarihte sipariş verelim:

Kaydın ofseti, o tarihte < tarihiyle sayılan toplam kayıt sayısıdır. Bu size, diğer sorguları için ofset olarak kullanabileceğiniz numarası verir

SELECT COUNT(1) FROM ... WHERE date < "the-date" 

...

İlgili konular