[PHP/mysql] sorteren op priority, en snel aanpassen

Pagina: 1
Acties:
  • 357 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Deikke
  • Registratie: Juni 2004
  • Laatst online: 11:47
Hey allemaal,

Ik heb een klein probleempje waat ik zo snel even geen raad mee weet (omdat het zo omslachtig is).

Ik wil graag een lijst van items handmatig in een bepaalde volgorde kunnen zetten (priority), laagste nummer = bovenaan.

nu heb ik een kolom in mijn database voor priority, maar nu moet ik bij het verhogen eerst kijken wat de waarde nu is, welk record 1 hoger staat, vervolgens 2 update query's doen voordat er 1 is verhoogd.

Dit is wellicht iets simpeler bij het invoegen, maar daar moet je toch weer steeds de volgende insertid uitvinden en die in de priority stoppen om het onderaan de lijst te krijgen.

Is er mischien een effecientere manier om die aan te pakken, of is dit de enige manier om dit te bewerkstelligen?

Bij voorbaat dank!

Acties:
  • 0 Henk 'm!

Anoniem: 26421

Wat is het probleem bij:

PHP:
1
2
3
4
5
6
// find highest
$result = mysql_query("SELECT priority FROM tablename ORDER BY priority DESC LIMIT 1");
$highest = mysql_result($result,0,0);

// new row
mysql_query("INSERT INTO tablename (priority) VALUES (".($highest+1).")");


?

Daarnaast kan een autoincrement-veld je misschien helpen.

Edit:

Heb nog eens gelezen, en begrijp dat je rijen met elkaar wilt verwisselen.
Ook dit kan natuurlijk.

Flow;

- selecteer rijen van db sorteer op prior asc
- toon respecteivelijk elke rij
- controleer bij elke iteratie of er een rij bestaat met een hogere priority en if true, toon de optie om de priority van de rij te verhogen
- idem, alleen check of er een rij met een lagere priority bestaat

Daarmee moet het lukken en ja, je zult twee updates nodig hebben maar dat lijkt me vrij logisch.

[ Voor 52% gewijzigd door Anoniem: 26421 op 25-01-2006 18:23 ]


Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 15:49

Bosmonster

*zucht*

Je komt er niet omheen om eerst te kijken wat je nieuwe waarde moet worden, maar aangezien het gaat om hele simpele query's boeit het weinig om er 2 of 3 achter elkaar uit te voeren.

De handigste methode als je iets wilt verschuiven is het omdraaien van wat jij priority noemt, zo weet je zeker dat als er een keer wat verwijderd wordt het blijft werken.

Dus, stel je wilt iets naar boven verschuiven:

- opvragen priority van het bovengelegen item (1 eenvoudige select, al kun je die in je list natuurlijk ook al meenemen)
- de priorities van je huidige item en die van die er boven omdraaien en wegschrijven


PHP:
1
2
$result = mysql_query("SELECT priority FROM tablename ORDER BY priority DESC LIMIT 1");
$highest = mysql_result($result,0,0);


Wat is er mis met

SELECT MAX(priority) FROM tablename

hoeft de db tenminste niet de hele tabel te sorteren alleen voor het ophalen van het hoogste item.

[ Voor 31% gewijzigd door Bosmonster op 25-01-2006 18:48 ]


Acties:
  • 0 Henk 'm!

  • Deikke
  • Registratie: Juni 2004
  • Laatst online: 11:47
dat met max werkt alleen voor INSERT's, maar in dit geval zal ik me dus bij het omhoog/omlaag schuiven eerst uit moeten zoeken waar hij nu staat, en dan zoeken welke er het dichtste bij staat. (omdat er bij het deleten priority's kunnen verdwijnen) Mja dat moet dan maar zo.

Ik heb verders geen idee hoeveel veel kleine queries voor impact op de database hebben, maar ik heb altijd zoiets van: "hoe meer, hoe langzamer". Maar ik vond deze methode nogal omslachtig om te laten werken, maar het is eigenlijk de enige manier van werken.

Trouwens: bij mijn weten kan maar 1 kolom auto_increment zijn, en die is al primary index (die eigenlijk niet gebruikt wordt)

[ Voor 13% gewijzigd door Deikke op 25-01-2006 19:20 ]


Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 15:49

Bosmonster

*zucht*

Een beetje eenvoudige query (bijvoorbeeld kijken welke in de priority volgorde boven een item staat) zou niet langer dan misschien een duizendste van seconde moeten duren. Dit eenvoudige werk is juist waar MySQL sterk in is.

Meer dan een select (en die is nog weg te optimaliseren als je de volgordes al meeneemt in je list) en 2 updates heb je niet nodig voor het verschuiven van een item. Een whopping 2-3 duizendsten van een seconde!

[ Voor 12% gewijzigd door Bosmonster op 26-01-2006 11:10 ]


Acties:
  • 0 Henk 'm!

  • wizzkizz
  • Registratie: April 2003
  • Laatst online: 05-06 12:47

wizzkizz

smile...tomorrow will be worse

Ik neem aan dat je bijvoorbeeld een priority 1 - 10 hebt en je wilt het item met rating 5 een rating van 3 geven.

Dit zou je kunnen doen door alles met de rating 3 <= rating < 5 één te ophogen ( kan in SQL makkelijk met rating = rating + 1 WHERE rating >= 3 AND rating < 5) en vervolgens je item met rating 5 (waarvan je een unieke waarde, bijvoorbeeld een ID, moet kennen) op 3 zetten.

Er zijn nog wel meer manieren, maar in dit geval heb je in totaal maar 2 queries nodig om de rating te veranderen. Moet je alleen wel zorgen dat 1) rating dubbele waardes kan bevatten of de waarde van de te verplaatsten rating tijdelijk op -1 ofzo zetten en 2) dat je zorgt voor een rollback-mogelijkheid als een van beide queries niet uitgevoerd kan worden (is vast geen citical system, maar anders zou je heel eventueel twee items kunnen hebben met dezelfde priority).

Of je doet wat Bosmonster zegt, maar dan kun je volgens mij alleen per 1 naar boven schuiven en niet meerdere stappen in 1 keer. Dus van 10 naar 1 kan dan niet in 1 keer.

Make it idiot proof and someone will make a better idiot.
Real programmers don't document. If it was hard to write, it should be hard to understand.


Acties:
  • 0 Henk 'm!

  • Deikke
  • Registratie: Juni 2004
  • Laatst online: 11:47
dat is mischien een hele gemakkelijke manier om dit op te lossen, dat zorgt er ook voor dat er nooit een dubbele met dezelfde priority aanwezig is, en heb je ook geen problemen met gewiste rijen/priority's.

Acties:
  • 0 Henk 'm!

  • ATS
  • Registratie: September 2001
  • Laatst online: 03-06 06:47

ATS

Als je niet gehecht bent aan mooie getallen voor je priorities, dan kan je natuurlijk ook gewoon gebruik maken van floating point getallen. Dan is het een kwestie van één rij updaten naar de gemiddelde waarde van de rijen waar hij tussen moet komen.

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant


Acties:
  • 0 Henk 'm!

  • Deikke
  • Registratie: Juni 2004
  • Laatst online: 11:47
floating point is oplaatst ook uit de decimalen, dan zul je dus je tabel op het laatst weer moeten omnummeren, of niet?

Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 15:49

Bosmonster

*zucht*

wizzkizz schreef op donderdag 26 januari 2006 @ 11:32:


Of je doet wat Bosmonster zegt, maar dan kun je volgens mij alleen per 1 naar boven schuiven en niet meerdere stappen in 1 keer. Dus van 10 naar 1 kan dan niet in 1 keer.
Een willekeurige positie kan niet inderdaad (je wisselt altijd om en dat is dan een ongewenst effect), maar springen naar boven of onder is uiteraard geen probleem. Dat is een kwestie van de priority op MAX+1 of MIN-1 zetten. Uiteraard wel een SIGNED int gebruiken dan, dus dat je ook negatieve waarden kunt hebben.

[ Voor 9% gewijzigd door Bosmonster op 30-01-2006 18:28 ]


Acties:
  • 0 Henk 'm!

  • wizzkizz
  • Registratie: April 2003
  • Laatst online: 05-06 12:47

wizzkizz

smile...tomorrow will be worse

Bosmonster schreef op maandag 30 januari 2006 @ 18:27:
[...]


Een willekeurige positie kan niet inderdaad (je wisselt altijd om en dat is dan een ongewenst effect), maar springen naar boven of onder is uiteraard geen probleem. Dat is een kwestie van de priority op MAX+1 of MIN-1 zetten. Uiteraard wel een SIGNED int gebruiken dan, dus dat je ook negatieve waarden kunt hebben.
ja, dat wel, maar dan krijg je een prio-lijst die bijvoorbeeld van -23 tot en met + 14 loopt met allemaal gaten erin, vind ik niet zo netjes. En je kunt nog steeds niet van 8 naar 3 in een lijst van 10 zonder een boel stappen uit te voeren via 7-6-5-4.

[edit]
en je kunt een nieuwe taak ook niet makkelijk op plaats 4 laten binnenkomen bij jou, dan moet je alle bovenliggende items 1 voor 1 gaan opschuiven of alsnog mijn manier gebruiken ;)

[ Voor 13% gewijzigd door wizzkizz op 30-01-2006 18:43 ]

Make it idiot proof and someone will make a better idiot.
Real programmers don't document. If it was hard to write, it should be hard to understand.

Pagina: 1