Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [php][mysql] zmiana liczby porządkowej rekordu
mpps
post 6.02.2008, 17:51:50
Post #1





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 14.03.2003
Skąd: Szczecin

Ostrzeżenie: (0%)
-----


witam,
mam taki problem:
chcę zmieniać liczbę porządkową rekordu za pomocą skryptu php w trakcie uaktualniania danych w bazie.

wyglądać ma to tak:

1. stan początkowy:

position | rekord
-------------------
1 | rekord1
2 | rekord2
3 | rekord3
4 | rekord4
5 | rekord5

2. po zmianie:

position | rekord
-------------------
1 | rekord1
2 | rekord5
3 | rekord2
4 | rekord3
5 | rekord4

3. po kolejnej zmianie:

position | rekord
-------------------
1 | rekord1
2 | rekord2
3 | rekord5
4 | rekord3
5 | rekord4

  1. IF($position!=$rek[position]){
  2. mysql_query("UPDATE tabela SET position=position+1 WHERE position>=$position") OR die(mysql_error());
  3. }


powyższe rozwiązanie powoduje, że po każdym uaktualnieniu danych, czyli zmianie którejś z pozycji, te, które mają wyższą liczbę porządkową zwiększają ją o 1.
problem tkwi w tym, że jeśli po raz kolejny uaktualnię dane w tabeli, te z wyższą liczbą porządkową znowu zwiększają ją o 1.

wygląda to wtedy tak:

1. stan początkowy:

position | rekord
-------------------
1 | rekord1
2 | rekord2
3 | rekord3
4 | rekord4
5 | rekord5

2. po zmianie:

position | rekord
-------------------
1 | rekord1
2 | rekord5
3 | rekord2
4 | rekord3
5 | rekord4

3. po kolejnej zmianie:

position | rekord
-------------------
1 | rekord1
2 | rekord2
3 | rekord5
5 | rekord3
6 | rekord4

jak zastosować pętlę, żeby rekord3 miał lp 4 a rekord4 lp 5?

pozdrawiam

Ten post edytował mpps 6.02.2008, 17:52:57


--------------------
www.mpps.pl
park maszynowy: apache 2.2.22 | php 5.4.0 | MySQL 5.0.10 | phpMyAdmin 3.5.0 | notepad ++ | pilsner urquell
Go to the top of the page
+Quote Post
-Wieviór-
post 6.02.2008, 18:12:49
Post #2





Goście







Generalnie chcesz osiągnąć to, że podnosić powiedzmy rekord 5 o jeden do góry, i te co są nad nim, mają opadać pod niego, tak? Czyli po prostu masz powiedzmy menu, każdy link oddzielny rekord, i ustalasz ich pozycję, poprzez strzałki góra/dół w administracji, tak?
Go to the top of the page
+Quote Post
mpps
post 6.02.2008, 18:40:31
Post #3





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 14.03.2003
Skąd: Szczecin

Ostrzeżenie: (0%)
-----


nie,
chodzi o to, żeby po każdej zmianie pozycji rekordu w bazie liczby porządkowe były zawsze po kolei, czyli:
1.
2.
3.
4.
5.

a nie:
1.
2.
3.
6.
28.

za każdym uaktualnieniem bazy (UPDATE) liczba porządkowa rekordów z większym position byłaby zmieniana - niektóre w dół, niektóre w górę, niektóre nie zmieniałyby swojej pozycji.
jeśli dasz 5 po 1, to: 2->3, 3->4 a 4->5
kolejna zmiana - dajemy 2 po 1 i mamy: 5->3, 3->5, 4->6 (znika nam lp 4).
w ten sposób robią się coraz większe 'dziury' między cyferkami winksmiley.jpg
tego chcę uniknąć


--------------------
www.mpps.pl
park maszynowy: apache 2.2.22 | php 5.4.0 | MySQL 5.0.10 | phpMyAdmin 3.5.0 | notepad ++ | pilsner urquell
Go to the top of the page
+Quote Post
nowotny
post 6.02.2008, 22:40:21
Post #4





Grupa: Zarejestrowani
Postów: 875
Pomógł: 122
Dołączył: 2.02.2008

Ostrzeżenie: (0%)
-----


Ja wymyśliłem coś takiego:
  1. <?php
  2. $position_doc='7';//pozycja docelowa gdzie chcemy umiescic rekord
  3. $rekord='trzy';//nazwa rekordu ktory chcemy przesunac
  4.  
  5. $query='SELECT * FROM tabela WHERE rekord="'.$rekord.'"';
  6. $result=mysql_query($query);
  7. $res=mysql_fetch_assoc($result);
  8. $rekord_current_position=$res['position'];
  9.  
  10. if($rekord_current_position>$position_doc) {
  11. $direction='back';
  12. $query='SELECT * FROM `tabela` WHERE `position` BETWEEN '.$position_doc.' AND '.$rekord_current_position.';';
  13. }
  14. else {
  15. $direction='forw';
  16. $query='SELECT * FROM `tabela` WHERE `position` BETWEEN '.$rekord_current_position.' AND '.$position_doc.';';
  17. }
  18.  
  19. $result=mysql_query($query);
  20. while ($row = mysql_fetch_assoc($result)) {
  21. if($row['position']==$rekord_current_position){
  22. $query='UPDATE tabela SET position="'.$position_doc.'" WHERE rekord="'.$row['rekord'].'"';
  23. }
  24. else{
  25. if($direction=='forw'){
  26. $query='UPDATE tabela SET position="'.($row['position']-1).'" WHERE rekord="'.$row['rekord'].'"';
  27. }
  28. else{
  29. $query='UPDATE tabela SET position="'.($row['position']+1).'" WHERE rekord="'.$row['rekord'].'"';
  30. }
  31. }
  32. mysql_query($query);
  33. }
  34. ?>


I mam nadzieje że nie masz pola "position" zdefiniowanego jako AUTOINCREMENT... winksmiley.jpg

Ten post edytował nowotny 6.02.2008, 22:41:36
Go to the top of the page
+Quote Post
-Wieviór-
post 7.02.2008, 13:33:28
Post #5





Goście







Cytat(nowotny @ 7.02.2008, 00:40:21 ) *


Ogólnie wygląda to dobrze chyba, tylko trzeba pamiętać, że w pierwszym if'ie else oznacza =<, a więc też gdy są sobie równe, i choć nic to nie zmieni, to warto dodać elseif < i elseif =, bo nie trzeba wtedy robić zapytania do bazy.

Inna sprawa, że proponuję lekką optymalizacje:

  1. <?php
  2. $position_doc='7';//pozycja docelowa gdzie chcemy umiescic rekord
  3. $rekord='trzy';//nazwa rekordu ktory chcemy przesunac
  4.  
  5. $query='SELECT position FROM tabela WHERE rekord="'.$rekord.'"';
  6. $result=mysql_query($query);
  7. $rekord_current_position=mysql_fetch_assoc($result);
  8.  
  9. if($rekord_current_position>$position_doc) {
  10. $direction='back';
  11. $query='SELECT position FROM `tabela` WHERE `position` BETWEEN '.$position_doc.' AND '.$rekord_current_position.';';
  12. }
  13. else {
  14. $direction='forw';
  15. $query='SELECT position FROM `tabela` WHERE `position` BETWEEN '.$rekord_current_position.' AND '.$position_doc.';';
  16. }
  17.  
  18. $result=mysql_query($query);
  19. while ($row = mysql_fetch_assoc($result)) {
  20. if($row==$rekord_current_position){
  21. $query='UPDATE tabela SET position="'.$position_doc.'" WHERE rekord="'.$row['rekord'].'"';
  22. }
  23. else{
  24. if($direction=='forw'){
  25. $query='UPDATE tabela SET position="'.($row['position']-1).'" WHERE rekord="'.$row['rekord'].'"';
  26. }
  27. else{
  28. $query='UPDATE tabela SET position="'.($row['position']+1).'" WHERE rekord="'.$row['rekord'].'"';
  29. }
  30. }
  31. mysql_query($query);
  32. }
  33. ?>


Nie potrzebne używać * i tworzyć tablicę, wyczytując całą tabelę z bazy danych, jeśli używamy tylko position ;]
Go to the top of the page
+Quote Post
mpps
post 7.02.2008, 15:22:59
Post #6





Grupa: Zarejestrowani
Postów: 242
Pomógł: 0
Dołączył: 14.03.2003
Skąd: Szczecin

Ostrzeżenie: (0%)
-----


Cytat(nowotny @ 6.02.2008, 22:40:21 ) *
I mam nadzieje że nie masz pola "position" zdefiniowanego jako AUTOINCREMENT... winksmiley.jpg

no, jak bym używał do 'position', to nie potrzebowałbym takiego rozwiązania - za które bardzo Ci dziękuję, bo po lekkich modyfikacjach działa doskonale! Modyfikacje nie wpływają na funkcjonalność, dlatego nie będę zaśmiecał nimi tutaj miejsca. jeszcze raz wielkie dzięki!!
jeśli komuś (może mi?) będzie się chciało, to może na podstawie Twojego rozwiązania rozwinąć temat i stworzyć np. skrypt do numerowania 'na nowo' danych w bazie.
spotkałem się na tym forum wielokrotnie z pytaniem o możliwość optymalizacji bazy pod kątem nadania nowego 'id' w sytuacji, kiedy używa się 'auto_increment' i wiadomo, że po wyrzuceniu jakiegoś rekordu powstają 'dziury'.
wiem, wiem, że zmiana 'id' może powodować błędy, itd, bla, bla, ale są takie sytuacje, kiedy taka zmiana jest pożądana!

Cytat(Wieviór @ 7.02.2008, 13:33:28 ) *
Inna sprawa, że proponuję lekką optymalizacje:
Nie potrzebne używać * i tworzyć tablicę, wyczytując całą tabelę z bazy danych, jeśli używamy tylko position ;]

a nie prawda!
jak zassiesz z bazy tylko 'position', to jest problem, ponieważ nie zostanie zmieniona pozycja elementu, który już taką pozycję ma (pole nie jest 'primary', bo być nie może)!
czyli, jeśli zmienisz 9->6, to 6->6 a nie 6->7
jeszcze nie wiem czemu ale właśnie to sprawdzam

od siebie dodaję zmianę w sytuacji usuwania rekordu:
  1. $result = mysql_query("SELECT * FROM tabela WHERE id=$id") OR die(mysql_error());
  2. $rek = mysql_fetch_array($result);
  3. mysql_query("DELETE FROM tabela WHERE id=$id") OR die(mysql_error());
  4.  
  5. // zmiana position dla wpisow z wyzszymi pozycjami
  6. $rekord=$id; //id rekordu, ktory usuwamy
  7. $rekord_current_position=$rek[position]; //position rekordu, ktory usuwamy
  8.  
  9. $query="SELECT * FROM tabela WHERE position>$rekord_current_position";
  10.  
  11. $result=mysql_query($query);
  12. while($row = mysql_fetch_assoc($result)){
  13. $query="UPDATE tabela SET position=($row[position]-1) WHERE id=$row[id]";
  14. mysql_query($query);
  15. }

proste ale jeśli ktoś będzie potrzebował, to ma komplet

pozdrawiam i dzięki!

Ten post edytował mpps 7.02.2008, 15:36:01


--------------------
www.mpps.pl
park maszynowy: apache 2.2.22 | php 5.4.0 | MySQL 5.0.10 | phpMyAdmin 3.5.0 | notepad ++ | pilsner urquell
Go to the top of the page
+Quote Post
-Wieviór-
post 7.02.2008, 15:32:11
Post #7





Goście







Słusznie, nie zauważyłem, że tam się jeszcze pole rekord pojawia. No to daj wszędzie zamiast "tabela" - "rekord, tabela". No chyba, że to są jedyne pola w tej tabeli, wtedy możesz dać rzeczywiście * ;]
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.06.2025 - 06:36