[MySQL+PHP] Rij tussen twee al bestaande zetten

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Ik ben bezig met een soort van CMS waarmee je pagina's kunt aanmaken in een pagina overzicht. De pagina's kun je sorteren mbv een omhoog en naar beneden pijl. Maar ik wil ook een knop om een pagina tussen twee andere te zetten.

Wat ik zou kunnen doen is iedere pagina (vanaf nu een rij) een order nummer te geven. Wanneer de tabel er bijv. zo uitzien:
code:
1
2
3
4
5
6
7
8
pagina_id | order_nr
1         | 1
2         | 2
3         | 3
5         | 4
7         | 5
8         | 6
9         | 7

en ik wil een rij onder pagina_id 1 zetten moet ik dus alle verdere order_nr's eentje opschuifen. Dit is een met een stuk PHP code is dit redelijk eenvoudig op te lossen maar is het niet mogelijk om met een handig truukje dit op te lossen?

[ Voor 4% gewijzigd door Slagroom op 19-07-2004 10:46 ]


Acties:
  • 0 Henk 'm!

  • MisterData
  • Registratie: September 2001
  • Laatst online: 29-08 20:29
gewoon:

SQL:
1
UPDATE pages SET order_nr=order_nr+1 WHERE order_nr>iets


Waarbij 'iets' dan aangeeft waar je hem wil hebben :?

Acties:
  • 0 Henk 'm!

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Maar dan heb je kans dat je twee gelijke order_nr's hebt...

Acties:
  • 0 Henk 'm!

  • MisterData
  • Registratie: September 2001
  • Laatst online: 29-08 20:29
Slagroom schreef op 19 juli 2004 @ 10:46:
Maar dan heb je kans dat je twee gelijke order_nr's hebt...
Tsja, dan moet je iets met locking of transacties doen denk ik.... Je kunt het ook als volgt doen: je hebt twee items: A heeft order_nr 1000 en B heeft order_nr 2000 (of een ander groot getal). Wil je daar nou een item tussen hebben, dan geef je dat nieuwe item order_nr = (2000-1000)/2 + 1000 = 1500. Sorteer je dan op order_nr dan komt alles in de goede volgorde. Ook kun je nu tussen ieder item items toevoegen zonder dat je met order nummers hoef te schuiven (hoewel locking of transacties toch wel nodig blijft) :)

Overigens kom je op een gegeven moment wel in de problemen, want als je op deze manier je order_nr opslaat kom je op een gegeven moment aan een maximum :)

[ Voor 11% gewijzigd door MisterData op 19-07-2004 10:49 ]


Acties:
  • 0 Henk 'm!

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Maar met lockings voorkom je geen dubbele order_nr's...

Ja, dat klopt, en dat wil ik eigenlijk niet. Eigenlijk hoop ik op een kunstje dat je gewoon een nummer kunt tussenvoegen zonder al te poespas.

[ Voor 18% gewijzigd door Slagroom op 19-07-2004 11:16 ]


Acties:
  • 0 Henk 'm!

  • Shedman
  • Registratie: November 2000
  • Laatst online: 05-07 15:38

Shedman

Met het hart op de goede plek

Kun je niet beter een veld 'id_vorige' invoegen waarin je het pagina_id van de pagina erboven invoert?
Dan hoef je bij het wijzigen van de volgorde alleen maar degene die nu aan de vorige pagina is gelinkt aan diegene waar je iets mee doet linken en dan die weer aan de goede vorige. Hmmm ... wazug dit.

Misschien verduidelijkt dit mijn hersenspinsel:
code:
1
2
3
4
pagina_id | id_vorige
1         | null
2         | 1
3         | 2

wordt dan
code:
1
2
3
4
pagina_id | id_vorige
1         | null
2         | 3
3         | 1

Dan hoef je ieg van elke row niet iets te veranderen. Alleen als je verderop in de lijst er een tussenuit haalt, moet je diens vorige nog weer ff koppelen aan diens initiele volgende.

Was Algoritmen en Datastructuren toch nog ergens goed voor :P

[ Voor 16% gewijzigd door Shedman op 19-07-2004 11:40 . Reden: Iets vergeten ... ]

Hier stonden al heel lang linkjes naar sites die het allang niet meer deden ...


Acties:
  • 0 Henk 'm!

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
En dan kan ik toch gewoon een SELECT doen en sorteren op id_vorige?

Acties:
  • 0 Henk 'm!

  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04 20:48
Is het dan niet iets directer om een ID-volgende op te nemen i.p.v. id-vorige?

Ik neem namelijk aan de pagina's vaker worden bekeken dan dat zij gewijzigd worden, en dan is een id_volgende denk ik practischer. Of gewoon beide, maar dat moet je dan weer consistent houden.

[ Voor 57% gewijzigd door kasper_vk op 19-07-2004 12:06 ]

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


Acties:
  • 0 Henk 'm!

Verwijderd

Dat is een beetje eng; je bent dan een (single of double) linked list aan het bouwen in SQL. Dat kan me nooit de bedoeling lijken.
UPDATE pages SET order_nr=order_nr+1 WHERE order_nr>iets

Waarbij 'iets' dan aangeeft waar je hem wil hebben
Maar dan heb je kans dat je twee gelijke order_nr's hebt...
Wat bedoel je? Met die UPDATE query krijg je helemaal geen twee gelijke order_nr's... er komt alleen een gat tussen order nummer iets en iets + 2. En je kan de nieuwe dan neerzetten op iets + 1.

Acties:
  • 0 Henk 'm!

  • Shedman
  • Registratie: November 2000
  • Laatst online: 05-07 15:38

Shedman

Met het hart op de goede plek

Ik denk dat beide ieg geen goed idee is. Volgende is misschien inderdaad wel beter. Dan kun je ook makkelijk het einde van de lijst vinden, omdat id_volgende null zal zijn.

Het lijkt me dat wanneer je iedere keer alle order_nr's gaat bijwerken, je nogal een load krijgt op het systeem. Dat is uiteraard afhankelijk van hoevaak het moet gebeuren en hoeveel rijen er in de tabel staan. Dan lijkt me de linked-list-achtige oplossing beter.

Maar ja, je eigen oplossing is altijd de beste ;)

[ Voor 14% gewijzigd door Shedman op 19-07-2004 14:03 ]

Hier stonden al heel lang linkjes naar sites die het allang niet meer deden ...


Acties:
  • 0 Henk 'm!

Verwijderd

Misschien... maar je code wordt er ingewikkelder en obscurer door.

Kijk en vergelijk:
  • Extra "order"-kolom, ophogen bij tussenvoegoperatie
    Lijstje weergeven: een beetje text aan de query toevoegen, daarna als gebruikelijk itereren over het resultaat
    Lijstje bijwerken: twee queries, eentje om op te hogen en eentje om in te voegen
  • Double linked list in tabel
    Lijstje weergeven: Eerst een tabel vullen (geïndexeerd op id) met alle rijen uit de database. Beginrij zoeken. Dan een pointer (index) in de tabel maken, en bij elke rij pointer updaten. Kàn. Als je in PHP iterators zou hebben zou dit nog niet eens heel lelijk hoeven zijn, omdat je de details dan kan verbergen, maar die heb je niet. Dus je zult of iterators moeten maken of genoegen moeten nemen met lelijke code.

    Lijstje bijwerken: drie queries; een om het record in te voegen en twee om pointers bij te werken. Plus lekker vage code.
Ik weet niet... ik zou 't niet doen.

Mijn gevoel roept gewoon heel hard "nee!".

Misschien de belangrijkste reden: Paginering. Met een order-kolom kun je het DBMS laten pagineren (LIMIT x, page_size). Met een linked-list gaat dat niet; daar is het altijd alle records ophalen en met de hand pagineren. Daar gaat je optimalisatie :/.

[ Voor 13% gewijzigd door Verwijderd op 19-07-2004 14:16 ]


Acties:
  • 0 Henk 'm!

  • Slagroom
  • Registratie: Juni 2001
  • Laatst online: 05-10-2024
Verwijderd schreef op 19 juli 2004 @ 13:17:
Dat is een beetje eng; je bent dan een (single of double) linked list aan het bouwen in SQL. Dat kan me nooit de bedoeling lijken.


[...]


[...]


Wat bedoel je? Met die UPDATE query krijg je helemaal geen twee gelijke order_nr's... er komt alleen een gat tussen order nummer iets en iets + 2. En je kan de nieuwe dan neerzetten op iets + 1.
Sorry, ik had je niet goed begrepen. Deze oplossing is enorm eenvoudig en gewoon goed! Ik zat te moeilijk te denken! Bedankt, ik zal het hiermee proberen!

Acties:
  • 0 Henk 'm!

  • Shedman
  • Registratie: November 2000
  • Laatst online: 05-07 15:38

Shedman

Met het hart op de goede plek

Verwijderd schreef op 19 juli 2004 @ 14:12:
Misschien... maar je code wordt er ingewikkelder en obscurer door.

Kijk en vergelijk:
  • Extra "order"-kolom, ophogen bij tussenvoegoperatie
    Lijstje weergeven: een beetje text aan de query toevoegen, daarna als gebruikelijk itereren over het resultaat
    Lijstje bijwerken: twee queries, eentje om op te hogen en eentje om in te voegen
  • Double linked list in tabel
    Lijstje weergeven: Eerst een tabel vullen (geïndexeerd op id) met alle rijen uit de database. Beginrij zoeken. Dan een pointer (index) in de tabel maken, en bij elke rij pointer updaten. Kàn. Als je in PHP iterators zou hebben zou dit nog niet eens heel lelijk hoeven zijn, omdat je de details dan kan verbergen, maar die heb je niet. Dus je zult of iterators moeten maken of genoegen moeten nemen met lelijke code.

    Lijstje bijwerken: drie queries; een om het record in te voegen en twee om pointers bij te werken. Plus lekker vage code.
Ik weet niet... ik zou 't niet doen.

Mijn gevoel roept gewoon heel hard "nee!".

Misschien de belangrijkste reden: Paginering. Met een order-kolom kun je het DBMS laten pagineren (LIMIT x, page_size). Met een linked-list gaat dat niet; daar is het altijd alle records ophalen en met de hand pagineren. Daar gaat je optimalisatie :/.
Hmmm... klinkt allemaal wel heel logisch wat je zegt.

Ik hou me verder wel stil ;)

[ Voor 5% gewijzigd door Shedman op 19-07-2004 21:56 ]

Hier stonden al heel lang linkjes naar sites die het allang niet meer deden ...

Pagina: 1