• User Attivo

    Ok, in questo caso però non ho fatto altro che ottenere tutti i giochi ai quali ha giocato IDUTENTE ... non c'è bisogno di fare un LEFT JOIN perchè se è vero che conosco l'id mi basta fare:
    SELECT gioco, punteggio
    FROM tbl_punteggi
    WHERE nick = $nick

    e ottengo lo stesso risultato.

    La cosa bella sarebbe determinare in che posizione è l'utente rispetto agli altri. Mi sembra strano che debba fare tante query quante sono i giochi.

    Ti ringrazio per l'aiuto e non vorrei abusare della tua gentilezza, quindi fermati quando vuoi 😉

    Grazie ancora


  • User

    @Bukowski said:

    La cosa bella sarebbe determinare in che posizione è l'utente rispetto agli altri. Mi sembra strano che debba fare tante query quante sono i giochi.

    Io userei

    SELECT nick, gioco, punteggio
    FROM nome_tabella_account
    LEFT JOIN nome_tabella_punteggi
    ON iduser = idnick
    WHERE iduser = <id_dell'utente>

    (cosi' avresti anche il nick... altrimenti puoi usare la tua query, ma il nick deve saltare fuori in altro modo)

    Poi per la posizione
    SELECT COUNT(*) FROM tbl_punteggi WHERE punteggio > <punteggio_utente> (lo passi via PHP)

    altrimenti se hai a disposizione una versione MySQl che supporta subqueries (> 4.1)
    SELECT COUNT(*) FROM tbl_punteggi WHERE punteggio > (SELECT punteggio FROM tbl_punteggi WHERE iduser = <id_dell'utente>)

    Una cosa del genere dovrebbe funzionare

    ciao


  • User Attivo

    Ok mi metto subito all'opera.

    Grazie ancora per il prezioso supporto.

    😉


  • User Attivo

    Allora secondo me ci siamo molto vicini, però non capisco una cosa ... dovrei fare tante query quanti sono i giochi per contare la posizione?

    Con questa query tiro fuori, di un determinato utente, tutti i giochi e i punteggi realizzati:
    SELECT nickpt, giocopt, puntipt
    FROM mp_classifiche WHERE nickpt= '$user';
    il risultato è giustamente:
    | BUKOWSKI | ARKANOID | 100.000 |
    | BUKOWSKI | FLIPPER | 755.000
    ecc ecc.

    E' l'altra che non so dove e come applicarla 😞

    Poi per la posizione
    SELECT COUNT(*) FROM tbl_punteggi WHERE punteggio > <punteggio_utente> (lo passi via PHP)

    Si ripeterà nel ciclo while di ogni riga per ogni gioco??

    Grazie ancora

    (Purtroppo ho del mysql la 4.0)


  • User

    Ci sono diversi metodi per affrontare il problema.

    Per esempio:
    preso un utente fai una query che ottenga nick, gioco e punteggio e le conservi in alcune variabili. Poi all'interno del loop chiami la query

    SELECT COUNT(*) FROM tbl_punteggi WHERE punteggio > <punteggio_utente> AND gioco = <gioco>

    e poi mandi in stampa tutto quello che ti serve.


  • User Attivo

    @nessuno said:

    Ci sono diversi metodi per affrontare il problema.

    Per esempio:
    preso un utente fai una query che ottenga nick, gioco e punteggio e le conservi in alcune variabili. Poi all'interno del loop chiami la query

    SELECT COUNT(*) FROM tbl_punteggi WHERE punteggio > <punteggio_utente> AND gioco = <gioco>

    e poi mandi in stampa tutto quello che ti serve.

    ok .. quindi però mi ritrovo ad avere tante query quante sono i giochi per quel determinato utente .. ovvero 40 ...

    ho paura che ritorno ad una situazione di pesantezza della query.


  • User

    Come ti dicevo prima ci sono sicuramente molti altri modi di affrontare questo problema, alcuni radicalmente diversi.

    IMHO anche 40 queries di quel tipo (vedi successivi commenti) non sono particolamente pesanti se il server e' correttamente dimensionato; sarebbero molto peggio un numero di queries inferiori ma molto piu' complicate.

    Ci sono altre valutazioni da fare sulla struttura del database e sull'ottimizzazione delle queries.

    Ti posto in seguito alcuni commenti.


  • User

    Per quanto riguarda la struttura del database

    @Bukowski said:

    In pratica ho 2 tabelle:
    # TABELLA ACCOUNT (20.000 record)

    • Qui ci sono i dati di registrazione dell'utente
      | iduser | nick | pwd
      esempio: 5 | Bukowski | peppino

    **# TABELLA PUNTEGGI ** (90.000 record)

    • Qui registro i punteggi fatti da ogni utente in ogni gioco
      | nickpt | gioco | punteggio | data
      esempio: | Bukowski | Arkanoid | 34000 | 12-12-2005
      esempio: | Nessuno | Flipper | 15000 | 10-12-2005

    In accordo con le regole di [url=http://it.wikipedia.org/wiki/Normalizzazione_del_database]normalizzazione di un database, in particolare, in questo caso, la Seconda Forma Normale, la tabella tbl_punteggi andrebbe scomposta in due tabelle con la seguente struttura:

    tbl_punteggi
    | nickpt | gioco_id | punteggio | data (assumo che nickpt sia un indice che si riferisce alla tabella degli utenti)

    tbl_giochi
    gioco_id | gioco_name

    Questo implica un serie notevole di vantaggi:

    • nella clausola WHERE non metti un nome ma un numero per cui la query richiede meno elaborazione, per cui termina piu' rapidamente.
    • nei 90000 records della tbl_punteggi avrai solamente dei numeri (tinyint da 1 byte possibilmente) invece che lettere (VARCHAR da 8 + 1 byte nel caso di Arkanoid)
    • se vuoi cambiare un nome di un gioco, lo cambi una sola volta e non in tutte le sue occorrenze fra quelle 90000 righe
    • e in ultimo... si fa cosi' ; )

  • User

    Con la struttura definita come nel precedente messaggio, sarebbe utile avere degli indici su:

    tbl_account.iduser (PRI)
    tbl_giochi.gioco_id (PRI)
    tbl_punteggi.nickpt (INDEX)
    tbl_punteggi.gioco_id (INDEX)

    Eventualmente io consiglierei di utilizzare tabelle INNODB e settare le foreign_keys.

    In questa maniera tutte le join verrebbero fatte su dei campi indicizzati per cui il carico elaborativo sarebbe minimo.

    Ulteriori ottimizzazioni potrebbero essere ottenute scegliendo adeguatamente i tipi di dati di ogni campo.

    Se posti l'output di un
    DESCRIBE nome_tabella
    oppure SHOW CREATE nome_tabella
    ti posso dare maggiori dettagli


  • User Attivo

    Accidenti, mi ero perso il proseguio di questo post .... 😮

    io devo mettermi a studiare perchè quello di cui hai scritto ho capito il 70%.

    A questo punto se dici che è meglio avere degli INT potrei trasformare la tabella punteggi in
    IDNICK (ora c'è il nome!) | IDGIOCO | PUNTEGGIO
    es: 6 | 9 | 54.000

    e quindi avere una tabella che riporta i nomi dei giochi
    IDGIOCO | NOMEGIOCO
    es: 1 | Arkanoid

    E' anche vero che cosi facendo mi troverò costretto a più parti a ricorrere a dei JOIN sia per ricavare il nome del gioco che il nick del giocatore.

    Giusto?


  • User

    @Bukowski said:

    E' anche vero che cosi facendo mi troverò costretto a più parti a ricorrere a dei JOIN sia per ricavare il nome del gioco che il nick del giocatore.

    Giusto?

    Si, ma ma avrai un database fatto secondo le regole e le prestazioni saranno superiori.

    E considera che le join su un database cosi' semplice sono un banalita'.