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
<?php
$randomok = array();
// Lekérdezzük az összes előforduló random értéket
$keres = mysql_query("SELECT random FROM tabla", $kapcsolat);
while ($sor = mysql_fetch_row($keres)) {
  $randomok[] = $sor[0];
}
// Megnézzük, mi a nem előforduló érték.
$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"
<?php
// Generálunk egy random számot
$random = rand(1,3);
// Megnézzük létezik-e az elem az adatbázisban
$keres=mysql_query("SELECT * FROM tabla WHERE random='$random'",$kapcsolat);
// Talált elemek száma
$sorok_szama=mysql_num_rows($keres);
// Ha van kapott sor, akkor végtelen ciklusba kerülünk, 
//mivel sehol nem módosul a $sorok_szama, azaz mindig igaz lesz.
while ($sorok_szama>0) {
  // Generálunk egy random számot??? miért???
  // az újonnan generált szám előfordulhat az adatbázisban, és
  // akár meg is egyezhet a korábban generálttal.
  $random=rand(1,3);
  // A sorok száma nem változik, mivel nem volt újabb lekérdezés
  $sorok_szama=mysql_num_rows($keres);
}
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.
<?php  
// Vesszük a számokat, majd összekeverjük,
// így minden szám 1 és 3 között pontosan egyszer fog előfordulni.
$randomok = range(1, 3);
shuffle($randomok);
// Kivesszük az utolsó elemet a tömbből, ami ugye mostmár véletlen sorrendű
$random = array_pop($random);
//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);
// Csak addig megyünk míg miden számot nem használtunk fel,
// vagy amíg nem találunk olyat, ami nem fordul elő
while ($sorok_szama > 0 && count($randomok)) {
  // Kivesszük az utolsó elemet a tömbből
  $random=array_pop($randomok);
  // Megnézzük, előfordul-e
  $keres = mysql_query("SELECT * FROM tabla WHERE random='$random'",$kapcsolat);  
  $sorok_szama=mysql_num_rows($keres);  
}

// Eredmény
if ($sorok_szama == 0) {
  $eredmeny = $random;
}
else {
  // nincs eredmény, minden szám benne van már az adatbáziban.
}
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.