Tablo girişleri sipariş

6 Cevap php

Peki bu saçma bir soru gibi ses gidiyor, biliyorum. Bu muhtemelen yapmak için en belirgin şeylerden biridir, ama ben veritabanı girişlerini sıralama iyi bir yol ile gelip çalışıyorum.

Bu gibi bakarak resim tablosu:

entry_id   |   entry_data
-------------------------
1          | data1
2          | data2
...        | ...
n          | datan

entry_id is of course Primary Key with AI option so all entries have a unique id. Now. I want to order that data. Say I want entry_id = 2 to be first without changing its entry_id. Then the table needs another column to store order number. I tried 2 approaches.

  1. entry_order_no: Bu temelde öğeleri sipariş numarasını tutacak. Herhangi yeni bir öğe her zaman sonuna eklenecektir.

  2. left_id + right_id, bu yaklaşım phpBB tarafından kullanılır. Değil emin niçin bu olsa right_id gerektirir?

I seem to prefer the 1st approach, but how do you sort the data later. Let's assume I want to newly added item move from the last position, to say 2nd. Way I've been doing it I was using indexed tables, where index was order no. Each index contained associative array, that had entry_id. That way I "simply" did foreach loop with an UPDATE on all entries from 2nd place down. That may work for few rows. Maybe even tens. But what when you have hundreds? This seems highly inefficient then. Second one seems a bit better. But something still tells me there's a better approach.

Önerirsiniz lütfen.

6 Cevap

Bunu yapmak için çalışıyoruz neden gerçek doğası emin değilim, bu yüzden bu tür söylemek zor, ama kadarıyla verimsiz foreach döngü gibi, setleri üzerinde iteratif yöntemleri kullanarak durdurmak - kullanım küme işlemleri, onlar yol konum hızlı ve DB için anlamı tam olarak ne. böylece yerine ...

for row in db>2
	entryorderno += 1

Bu do ...

UPDATE Table
SET entryorderno = entryorderno + 1
WHERE entryorderno > 2

Ayrıca, bu süre oldukça ok olmalı, ama sonunda yeni aralığı ile her şeyi yeniden düzeltin gerekecek, Alex Martelli söylediklerini yapıyorsa çekerek .... ama bu alanda bir kümelenmiş dizin bu ID tarafından sırayla şeyleri tutmak olacaktır. ... Tabii o da büyük bir tablo ise masanın ortasına ekler kaynak yoğun olabilir anlamına gelir.

phpBB akıllı bir yaklaşım kullanıyor: left_id ve bir nested set parçası olarak bir ağacın düğümleri karşılık right_id. Bu muhtemelen (bu endişesi gibi görünüyor beri) performans bir sorun olacak, almak istediğiniz yoldur. İşte very thorough implementation walkthrough of nested sets bulunuyor.

Ama veritabanlarının genellikle sırasız veri içindir unutmayın. Sıralanmış verileri elde etmek için, genellikle ilgilenen ve daha sonra post-processing yaptığımız tüm satırları almak - örneğin, bir ORDER BY maddesi ile ya da geri geldim sonra sonuçları sıralayarak.

Eğer veri kendisi bir parçası olarak bir sipariş saklamak için gereken yere (o bilgisayarlı edilemeyen veya kullanıcı tercihine dayalı olduğundan, örneğin) olduğunu söyledi, bu genellikle sipariş tutan başka bir tablo ile veya ek sütunlar tarafından yapılır iç içe geçmiş bir-set yaklaşım, yukarıda belirtildiği gibi.

Biz ilkel Basic programlanmış geri biz ", 10, 20, 30 ..." satırları sayılı biz hiç mevcut olanlar arasında bir satır eklemek gerekirse biz sadece tüm diğerlerini numaralandırılmadan olmadan, diyelim ki, 25 bu sayı böylece. Onun tek amacı her şeyi yeniden numaralandırılmadan, satırlar 'sipariş tutmak ve henüz az yaygara ile bu düzeni değiştirmek için izin olup olmadığını (mysql dahili dizinini güncellemek zorunda kalacak, sizin "giriş sipariş" için benzer bir hile kullanabilirsiniz Bu sütun, ama bu, yine de daha büyük olasılıkla bunu kendiniz yaparak daha hızlıdır - Bu onaylamak için kurulum bazı kriterler deneyin). BIGINT ve large ilk artış kullanın, 1024 demek, ve bu sütunu yeniden gerekir önce epeyce reorderings için iyi olmalı.

İlginç bir soru. Left_id / right_id muhtemelen (sıralı aksine) hiyerarşik veri depolamak için iç içe set yaklaşımının bir uygulamasıdır. Bkz Trees in SQL.

Ben bu sorun için almış iki yaklaşım vardır. Bir kaba kuvvet bir giriş değiştirilebilir / / eklenir ne zaman gerekli tüm numaraları ayarlamak nerede, tarif edilmektedir biridir. Diğer bir rütbe korumak, bu yüzden bir girdinin sıralaması yükselmiş olduğunda, sadece başkalarının yazıların sıralarında herhangi bir değişiklik yapmadan kendi rütbe sayısını artırmak için olduğunu. Kullanıcı yukarı oka tıkladığında her zaman, örneğin, girişin rank 1 ona eklenen alacağı ve düğüm listesinde bir düzey yukarı hareket ettiği durumda rütbe sıralaması listesinde, yeniden işlemek.

Eğer büyük bir veri kümesini bir kez olsun bu yaklaşımların hiçbiri ideal, ama genellikle bu noktada elle sıralama düzenini sürdürmek, ve otomatik olarak sıralamak için bir algoritma geliştirdiler artık.

Bir yapay sıralamayı (bazı sütunlar üzerinde sıralayarak dynamicaly yaratamazsınız bir sipariş) ihtiyacınız varsa, bir Position sütun eklemeniz gerekir. Eğer iki satırları yeniden sıralamak, size yoğun bir kodlama kullanıyorsanız, bunların arasındaki tüm satırları değiştirmek zorunda.

Örneğin ilk satır böylece konumunu 100, ikinci 200, üçüncü 300 alır, ve - Sen kaybetmek kodlama kullanmak için seçeneğiniz vardır. Bu mantık karmaşıklığını artırmak, ancak birden fazla satır değiştirmek gerek kalmadan yeniden sıralama işlemleri bir dizi gerçekleştirmek için izin verecektir.

Basit bir sıralama düzeni sütun depolama ve veritabanı tetikler ve saklanan fucntions kullanmaya ne dersiniz?

The trigger would fire whenever you update an order column and increment all orders greater than the new order by 1. Hundreds or thousands of records should not be a problem for any decent database, especially when the processing is done internally to the DB, (I would not recommend doing this from within your application) though once you get into the tens of millions, updating that many rows would get troublesome.

Verilerinizin büyüklüğüne bağlıdır.