ugrás a tartalomhoz

PHP-Mysql

Pisti20 · 2010. Feb. 16. (K), 16.36
Először is üdv. ismét!

Van egy problémám, a következő:
Adott egy regisztráció, ahol az adatok tárolásán kívül, generálunk egy random számot, jelen esetben 1-3 között, és ezek egyedi értékek kell hogy legyenek.
<?php
$random=rand(1,3);
$keres=mysql_query("SELECT * FROM tabla WHERE random='$random'",$kapcsolat);
$sorok_szama=mysql_num_rows($keres);
while ($sorok_szama>0)
       {
        $random=rand(1,3);
        $sorok_szama=mysql_num_rows($keres);
       }


Ezzel azt szeretném elérni, hogy az adatbázisban, a táblát átböngészve, olyan random számot kapjak, amely 100% hogy nincs benne a táblában.
Jelen esetben mondjuk 2 lenne valamely már regisztrált felhasználó száma a táblában, akkor ha az új felhasználó regisztrációnál 2t generál, lefutáskor figyelembe véve hogy ez már egy generált, és táblában tárolt (UNIQUE) érték, új számot generáljon (1 vagy 3) , ami még nincs benne a táblában, így kizárva a duplikációt.
Nem szeretném hallani azt hogy "uhh de hülye" , és hasonló társaikat.
Segítségért jöttem fel, kérem aki megmondja mi a hibám, ami miatt nem megy, kerek mondatban foglalja össze ha elméleti, vagy gyakorlati hibám van.
Köszönöm
 
1

Nem előforduló

Poetro · 2010. Feb. 16. (K), 18.53
  1. <?php  
  2. $randomok = array();  
  3. // Lekérdezzük az összes előforduló random értéket  
  4. $keres = mysql_query("SELECT random FROM tabla"$kapcsolat);  
  5. while ($sor = mysql_fetch_row($keres)) {  
  6.   $randomok[] = $sor[0];  
  7. }  
  8. // Megnézzük, mi a nem előforduló érték.  
  9. $nem_elofordulo = array_diff(range(1, 3), $randomok);  
Mondjuk ilyen esetben a művelet előtt érdemes lock-olni a táblát, mert párhuzamosan, ha kettő script fut le, akkor az egyik hibás eredményt adhat.
2

folytasd kérlek

Pisti20 · 2010. Feb. 16. (K), 19.38
Pls folytasd, figyelek, próbálom értelmezni, de nem minden függvényt ismerek még.
a $nem_elofordulok=$maradt_lehetosegek nemde?
ebből hogyan vegyek ki értéket?
Miért nem jó továbbá az én megoldásom? hiszen elvileg mennie kellene. Hiba nincs benne, szintaktikailag 100%, de a logikám is követhető sztem.
3

A te megoldásod

Poetro · 2010. Feb. 16. (K), 20.01
Miért nem jó továbbá az én megoldásom?

Imhol leírom mit csinál a te "megoldásod"
  1. <?php  
  2. // Generálunk egy random számot  
  3. $random = rand(1,3);  
  4. // Megnézzük létezik-e az elem az adatbázisban  
  5. $keres=mysql_query("SELECT * FROM tabla WHERE random='$random'",$kapcsolat);  
  6. // Talált elemek száma  
  7. $sorok_szama=mysql_num_rows($keres);  
  8. // Ha van kapott sor, akkor végtelen ciklusba kerülünk,   
  9. //mivel sehol nem módosul a $sorok_szama, azaz mindig igaz lesz.  
  10. while ($sorok_szama>0) {  
  11.   // Generálunk egy random számot??? miért???  
  12.   // az újonnan generált szám előfordulhat az adatbázisban, és  
  13.   // akár meg is egyezhet a korábban generálttal.  
  14.   $random=rand(1,3);  
  15.   // A sorok száma nem változik, mivel nem volt újabb lekérdezés  
  16.   $sorok_szama=mysql_num_rows($keres);  
  17. }  
a $nem_elofordulok=$maradt_lehetosegek nemde?

Igen, ez azoknak a számoknak a listája amik még megmaradtak. Hagyományos tömb, minden tömb művelet engedélyezett rajta.
4

rendben

Pisti20 · 2010. Feb. 16. (K), 20.07
Rendben, ezek szerint az elméletem, nem igazán vált be, mindenesetre köszi, értem, és folytatom.
üdv
5

az elméletem

Pisti20 · 2010. Feb. 16. (K), 20.33
Ez az amit SZERETNÉM hogy tegyen azzal a forráskóddal amit megadtam :)
<?php  
     // Generálunk egy random számot, ez eddig oké is  
     $random = rand(1,3);  
     //A lekérdezés a generált számot keressi
     $keres=mysql_query("SELECT * FROM tabla WHERE random='$random'",$kapcsolat);  
     // Talált elemek száma  
     $sorok_szama=mysql_num_rows($keres);  
     // amíg a sorok száma nagyobb mint 0,
     // tehát van olyan rekord az adatbázisban amelyiknek
     // a random értéke = a generáltal addig fusson le
     while ($sorok_szama>0) {  
     // Generálunk egy random számot, mert a már generált benne van az adatbázisban  
     // az újonnan generált szám előfordulhat az adatbázisban, és  
     // akár meg is egyezhet a korábban generálttal, de ez nagy intervallumnál
     // már  kevésbé valószínű , és ha még is, 2.szorra szinte lehetetlen
     // ezt az álltalad alkalmazott függvényt sajnos még nem ismerem de folytatom  
     $random=rand(1,3);  
     // A sorok száma miért nem változik? Most a már újonnan generált értékkel
     // kellene lefutnia a ciklusnak. Elmondod hogy mi kellene hogy itt legyen
     // hogy változzon a sorok száma, és ne legyen végtelen ciklus?
    // Az új számmal már a lekérdezés elvileg 0-t ad vissza,
    // mert az új, 3as random pl elvileg nincs az adatbázisban, nem?
     $sorok_szama=mysql_num_rows($keres);  
    }
6

rand

Poetro · 2010. Feb. 17. (Sze), 02.59
A legfontosabb probléma, hogy nem látod, hogy a rand(1, 3) két egymást követő hívásban is adhat ugyanolyan eredményt, azaz simán előfordulhat hogy egymás után 3-szor 1-et ad. Pont mint ahogy a kockadobás esetén, lehet egymás után 4-szer 3-at dobni.
A másik ami miatt nem változott a $sorok_szama, mivel nem volt újabb lekérdezés.

Az persze mellékes, hogy az elgondolásod egyáltalán nem hatékony, mert legrosszabb esetben 3 lekérdezés szükséges, mire megállapítjuk, hogy egyáltalán nincsen olyan random szám, amit be tudnánk rakni a táblánkba, míg legjobb esetben egy lekérdezésből állapítja meg, hogy mi a szabad random.
Az én első megoldásomban egy lekérdezés alatt megvan, és a tömb rendezgetése sehol nincs teljesítmény igényben a 3 lekérdezéshez képest.
Ez főleg akkor lesz probléma ha nem 3 hanem 33333 kombinációból lehet választani, azaz mondjuk 1 és 33333 közötti random számot akarsz majd beszúrni, mivel ekkor a te elgondolásod alapján legrosszabb esetben 33333 lekérdezés szükséges, az 1 helyett.
  1. <?php    
  2. // Vesszük a számokat, majd összekeverjük,  
  3. // így minden szám 1 és 3 között pontosan egyszer fog előfordulni.  
  4. $randomok = range(1, 3);  
  5. shuffle($randomok);  
  6. // Kivesszük az utolsó elemet a tömbből, ami ugye mostmár véletlen sorrendű  
  7. $random = array_pop($random);  
  8. //A lekérdezés a generált számot keressi  
  9. $keres = mysql_query("SELECT * FROM tabla WHERE random='$random'",$kapcsolat);    
  10. // Talált elemek száma    
  11. $sorok_szama=mysql_num_rows($keres);  
  12. // Csak addig megyünk míg miden számot nem használtunk fel,  
  13. // vagy amíg nem találunk olyat, ami nem fordul elő  
  14. while ($sorok_szama > 0 && count($randomok)) {  
  15.   // Kivesszük az utolsó elemet a tömbből  
  16.   $random=array_pop($randomok);  
  17.   // Megnézzük, előfordul-e  
  18.   $keres = mysql_query("SELECT * FROM tabla WHERE random='$random'",$kapcsolat);    
  19.   $sorok_szama=mysql_num_rows($keres);    
  20. }  
  21.   
  22. // Eredmény  
  23. if ($sorok_szama == 0) {  
  24.   $eredmeny = $random;  
  25. }  
  26. else {  
  27.   // nincs eredmény, minden szám benne van már az adatbáziban.  
  28. }  
7

Hát jó

Pisti20 · 2010. Feb. 17. (Sze), 08.49
Értem a logikád, nem ezzel van a baj, hanem hogy olyan függvényeket használsz amiket még nem tanultunk.
Minden esetre akkor ezt a megoldást preferálom, és utána nézek ezeknek a dolgoknak.
Köszönöm a segítséget.
8

egy picit vitatkoznék,

h31st · 2010. Feb. 18. (Cs), 17.07
egy picit vitatkoznék, ordenáré nagy tábláknál nem feltétlen célravezető beolvasni mindent, inkább addig generálni randomot, míg nincs olyan. az más kérdés, hogy úgy nincs értelme, hogy 0 és a jelenlegi max érték között lövöldözünk vaktában, mert lehet, hogy csak 1-2 lyuk van, és azt random alapján megkeresni hosszú lesz :)
viszont van értelme, ha egy elég nagy intervallumba lövöldözünk, amiből viszonylag kevés használt elem van, pl 32karakteres hash-ek, és pár száz elem van a táblában... kicsi az esélye, hogy 1-2 lekérdezésnél tovább jusson, és nem kell beolvasni a sokszáz azonosítót, amik ráadásul egyenként 32 karakteresek...
illetve, jobb lenne adatbázisra bízni a random generálást, és akkor nem kell minden ellenőrzéshez php-ból query-t futtatni, de az már külön tudomány :)

viszont pl megkérdezném, hogy miért nem jó egy mysql primary key not null auto_increment megoldás, muszáj randomnak lennie?
9

Nem , randomnak kell lennie

Pisti20 · 2010. Feb. 21. (V), 13.36
Hali, a random muszáj, mert ha auto_increment akkor ki tudod következtetni a következőt, és a randomot nehezebb eltalálni. A random egy privát kulcs lesz, ami nem csupán a random számot tartalmazza.