Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Odszukiwanie int, liczenie, sumowanie i porównywanie w jednym
Forum PHP.pl > Forum > PHP
Morfi777
Witam,

Kompletnie nie mam pomysłu jak to rozegrać. Postaram się to przedstawić jak najlepiej.

Baza wygląda tak:

---user_id--------points---
-----1-------- 2, 4, 5, 1, 1
-----2-------- 1, 1, 1, 1, 1
-----3-------- 4, 5, 7, 2, 1
-----4-------- 1, 1, 1, 9, 9

Czyli jest 4(lub więcej) użytkowników i każdy ma jakieś tam punkty.


Co chcę uzyskać to: żeby skrypt wyciągnął z bazy wszystkich użytkowników i policzył im ile każdy ma punktów "1".
Czyli:
user 1 ma 2 x 1 -> 2
user 2 ma 5 x 1 -> 5
user 3 ma 1 x 1 -> 1
user 4 ma 3 x 1 -> 3


Dodatkowo ! Każdy user ma swój login. I chcę by po zalogowaniu widział on wszystkie punkty, ale żeby nie było zdradzone czyje to są punkty (oprócz niego samego).
Czyli: user 3 po zalogowaniu widzi
5
3
2
1 <- To są twoje punkty

a user 4 widzi:
5
3 <- To są twoje punkty
2
1


To tyle, bardzo proszę o podsuwanie pomysłów winksmiley.jpg
Crozin
Zły projekt bazy. Powinieneś mieć osobną tabelę z kolumną user_id (będącą odniesieniem do id z tabeli user) oraz drugą kolumnę point. Przy pomocy standardowych COUNT(), GROUP itp. byłbyś w stanie takie rzeczy wyciągnąć.
Morfi777
Dziękuję za odpowiedź!

Uh... rozumiem, że tak musi być ze względu na ten wyjątek co do wyświetlania danych dla konkretnych osób tak ?

Z tym akurat nie powinno być problemu gdyż login jest np. user4 a wewnątrz jest funkcja explode która oddziela "4" i na tej podstawie wyszukuje z bazy po user_id.


Zapomniałem wspomnieć o 1 ważnej rzeczy (na początku wydawała mi się nieważna, ale teraz widze ze jest).

Czasami elementy się powtarzają tj.

---user_id--------points---
-----1-------- 2, 4, 5, 1, 1
-----2-------- 1, 1, 1, 1, 1
-----3-------- 4, 5, 7, 2, 1
-----1-------- 2, 1, 3, 4, 1
-----2-------- 7, 8, 9, 1, 1
-----1-------- 8, 1, 1, 1, 2
-----4-------- 1, 1, 1, 9, 9


Czyli user_id może się powtórzyć nawet kilka razy! Nie należy milyć user_id ze zwykłym "id" który jest kluczem podstawowym + auto_incr.

czy to coś zmienia ?
Wtedy te "1" są wyciągane z 3 rekordów i wszystkiee musiałyby być zsumowane



Pozdrawiam
Crozin
1) Te points to co to ma być w ogóle?
2) Tak powinno być ponieważ zapewne pracujesz z bazą dla której jest to bardziej naturalny format zapisu danych (np. PostgreSQL)
3) W pewnych przypadkach można zapisywać takie coś w postaci "1,2,3,45,6,7" - ale ten raczej nie jest takim przypadkiem.
phpion
Jak już wspomniano wcześniej projekt bazy jest do kitu. No ale skoro jest jak jest to możesz policzyć wystąpienia znaków poprzez count_chars. Liczy to liczby wystąpień znaków, czyli jeśli ktoś będzie miał np. 11 to policzy to jako 2 wystąpienia 1, a nie 1 wystąpienie 11. Jeżeli liczby te masz z przedziału 0-9 (czyli cyfry) to nie będzie problemu.
Morfi777
To mogło by rozwiązać mój problem.

Ale oczywiście jestem otwarty na sugestie lub uwagi bo to pozwoli mi uniknąć błędów w przyszłości.

@crozin, prosiłes o wyjaśnieni
Na stronie używam (niestety gotowego) aczkolwiek bardzo bardzo fajnego mysqlajaxtableeditor.
To jest taki panel do wpisywania rekordów przy użyciu AJAX. Po wprowadzeniu własnych pól struktura wygląda tak:

Cytat
----id----numer----punkty-----

id -- oczywiscie, primo + auto increment
nr -- to numer zawodnika
punkty -- to punkty jakie zdobył w danej rundzie

rund jest kilka(pięciu sędziów i każdy wystawia punkt), ale ich nie ma w bazie bo nie potrzebowałem tych danych. Tak więc czasami nr zawodnika się powtarza

No i jak już napisalem, moze to wygladać tak
Cytat
----id----numer----punkty-----
----1------1----- 2, 4, 5, 1, 1
----2------1----- 3, 9, 8, 1, 1
----3------1----- 4, 5, 1, 1, 2
----4------2----- 1, 3, 3, 2, 6
----5------2----- 7, 8, 1, 9, 8


No i teraz chciałem stworzyć takie Hall of Shame czyli żeby podliczył ile dany zawodnik ma w sumie punktów "1".

W tym przypadku zawodnik 1 ma 6 x 1 czyli 6 takich punktów, a zawodnik 2 x 1 czyli 2 takie punkty smile.gif
No i to co mówiłem, żeby zawodnik 1 po zalogowaniu się widział wszystkie punkty, ale żeby tylko przy jego ilości pokazało się, że są to jego punkty.


Czy teraz jest to jasne ? smile.gif


W takim razie co powinienem zrobić w tej bazie żeby była bardziej elastyczna wg was ? winksmiley.jpg po prostu nie planowałem z początku takiego 'rankingu' i stąd ten problem
Crozin
Punkty powinny być w osobnej tabeli, każdy w osobnym rekordzie. Dzięki temu przy pomocy COUNT() i GROUP BY będziesz w stanie określić ilość punktów każdego zawodnika.
Morfi777
Coś zacząłem, ale nie radze sobie

  1. $sql="SELECT * from gracze WHERE nr=29";
  2. $wynik=mysql_query($sql)or die("zle pytanie2".$sql);
  3. while ($rekord=mysql_fetch_row($wynik)){
  4. $ones = $rekord[4]." ".$rekord[5];
  5. $wydziel = substr_count($ones, "1");
  6. $policz += $wydziel;
  7. echo $policz;
  8. }


W wyniku dostaje 2,2,2,2,2,2,2,2,2,3,3,3,3,3,3 zamiast samego 3 sad.gif

dlatego ze jest 15 rund, a w sumie punktow 1 było 3.


Jak pokazać tylko ostatni (15) wynik?
Crozin
No ale przecież napisałem, że powinieneś przede wszystkim zmienić fatalną strukturę bazy danych.
Morfi777
W porządku, wiem co napisałeś tyle że w tym przypadku to jest a wykonalne jeżeli dalej mam używać tego panelu.


Powiedz mi chociaż jak się wyświetlają te liczby, co to jest. te 222222222333333
Bo to nie jest 1 string tylko 15 rożnych ciągów (po 1 znaku). To też nie jest array, to co to jest ? I jak mogę odseparować tylko ostatni z nich ?
thek
Jeśli zależy Ci na określonym znaku to użyj substr. Przy czym przydaną ciekawostką jest używanie tam parametrów ujemnych, co nieraz się przydaje. Nawet w twoim przypadku dobrą alternatywą, bo ostatni element ciągu znakowego to
substr($ciag, -1)
Popatrz na manual i przykłady w nim oraz komentarzach do tej funkcji bo jest to prosto wytłumaczone tam.
Morfi777
Dzięki, ale właśnie powiedziałem, że to nie działa ponieważ to jest 15 różnych ciągów,a nie 1 !
To że on się wyświetla razem nie oznacza, że jest to 1 string sad.gif

Stąd moje pytanie. Skoro to NIE jest 1 ciąg, i to nie jest array(15). To co to jest ? I jak to odseparować.
thek
Teraz zauważyłem, że to nie konkatenacja tylko zwykle dodawanie smile.gif Zauważ, że to tak naprawdę pętla gdzie sprawdza ile razy wystąpiła w rundzie jedynka ( $wydziel ) i dodaje to wciąż do zmiennej $policz. Musisz więc sie do niej odwołać po zakończeniu pętli. Jako że jest ona zmienną lokalną dla while, to po zakończeniu pętli jest ona niszczona. Dlatego musisz minimalnie zmienić poprzednią część do postaci:
  1. $sql="SELECT * from gracze WHERE nr=29";
  2. $wynik=mysql_query($sql)or die("zle pytanie2".$sql);
  3. $policz = 0; //dzięki temu będzie to "zmienna globalna" dla pętli
  4. while ($rekord=mysql_fetch_row($wynik)){
  5. $ones = $rekord[4]." ".$rekord[5];
  6. $wydziel = substr_count($ones, "1");
  7. $policz += $wydziel;
  8. }
  9. echo $policz; //dzieki wywaleniu przed pętlę tej zmiennej mamy do niej dostęp tutaj

Dzięki deklaracji i inicjalizacji $policz jeszcze przed pętlą, możemy się po zakończeniu pętli do niej odwołać.
Sprawdź sobie zresztą na kod a sam dojdziesz do wniosku, że to nie array, nie string, a poczciwy int, ale wielokrotnie wypisany na ekran smile.gif
Morfi777
Cytat(thek @ 29.10.2009, 01:43:15 ) *
Teraz zauważyłem, że to nie konkatenacja tylko zwykle dodawanie smile.gif Zauważ, że to tak naprawdę pętla gdzie sprawdza ile razy wystąpiła w rundzie jedynka ( $wydziel ) i dodaje to wciąż do zmiennej $policz. Musisz więc sie do niej odwołać po zakończeniu pętli. Jako że jest ona zmienną lokalną dla while, to po zakończeniu pętli jest ona niszczona. Dlatego musisz minimalnie zmienić poprzednią część do postaci:
[PHP] pobierz, plaintext
  1. $sql="SELECT * from gracze WHERE nr=29";
  2. $wynik=mysql_query($sql)or die("zle pytanie2".$sql);
  3. $policz = 0; //dzięki temu będzie to "zmienna globalna" dla pętli
  4. while ($rekord=mysql_fetch_row($wynik)){
  5. $ones = $rekord[4]." ".$rekord[5];
  6. $wydziel = substr_count($ones, "1");
  7. $policz += $wydziel;
  8. }
  9. echo $policz; //dzieki wywaleniu przed pętlę tej zmiennej mamy do niej dostęp tutaj
[PHP] pobierz, plaintext
Dzięki deklaracji i inicjalizacji $policz jeszcze przed pętlą, możemy się po zakończeniu pętli do niej odwołać.
Sprawdź sobie zresztą na kod a sam dojdziesz do wniosku, że to nie array, nie string, a poczciwy int, ale wielokrotnie wypisany na ekran smile.gif


Jestem Ci przeogromnie wdzięczny. Już nie raz miałem ten sam problem, że nie wiedziałem jak zachować zmienną PO wyjściu z pętli. Teraz już wiem, że wystarczy ją określić PRZED pętlą smile.gif smile.gif smile.gif


Pozdrawiam

Jak mogę posortować te liczby od największej do najmniejszej ?
thek
"Te liczby" to znaczy które? Wszystkie pojedyncze wypisania na ekran zmiennej $policz w pętli, które przybrały postać
2,2,2,2,2,2,2,2,2,3,3,3,3,3,3
i gdzie interesowała Cię tylko ostatnia czy jakieś inne liczby, które są przebiegiem choćby innej pętli, która jest nie dla jednego gracza, ale wszystkich?
Jeśli to drugie, to $policz dodawaj do jakiejś tablicy wraz z danymi określającymi gracza jakiego tyczą i potem tylko posortuj ją. Istnieją funkcje do sortowania tablic, więc zapoznaj się z nimi w manualu smile.gif
Jeśli jednak chciałbyś posortować owo 2,2,2,2,2,2,2,2,2,3,3,3,3,3,3 (nie widzę w tym sensu, ale to szczegół) to każdą $policz dodawaj jako kolejny element do tablicy i też ją potem posortuj.

EDIT: By Ci pomóc dodam, że masz zerknąć na te z "sort" w nazwie i u z przodu i zdefiniować własna funkcję porównująca wywoływaną jako callback, ale omiń usort, bo ona zlikwiduje Ci Twoje klucze zastępując własnymi ;)Brzmi trudno ale masz proste przykłady w manualu więc powinieneś dać sobie radę.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.