Newsgroup: it.comp.www.php
Titolo: [URGENTE] query complessa mysql

Salve raga',
tempo fa qlc mi diede la soluzione a questo problema, ma
adesso mi sono accorto che non funziona come dovrebbe
(grazie cmq a tale persona!!!!). Sono sicuro cmq che bisogna
usare MAX() e GROUP BY, ma come??
Il problema č questo:
Ho due tabelle :
tabella utenti con i campi:
user
category
tabella voti con i campi :
user
votes
Devo formulare una query che mi restituisce i vincitori per
ogni classifica, cioč se ci sono 100 utenti e 10 categorie,
devo ottenere 10 vincitori, ognuno per la sua categoria.
con la query 
SELECT user,category,MAX(votes) FROM utenti,voti WHERE
utenti.user=voti.user GROUP BY utenti.categoria 
Mi restituisce un utente per ogni categoria, ma stranamente
non prende quello che ha ricevuto piů voti rispetto alla sua
categoria.
Sto impazzendo! Aiutatemi. Deve essere tutto pronto fra
mezz'ora!!!!!
Thanks:)
-- 
WEbdOM webmaster di
Metronic.It mobile phone philosophy
www.gadgetpoint.it
 serigrafia on line

usare MAX() e GROUP BY, ma come??
E' bello vedere tante persone che si aiutano:)))
Se uso greatest() ??


Mmmh... Cavoli, più incasinato di quanto sembri. Eppure sembra una menata.
Ma a quanto pare mysql ti becca i valori giusti di votes, ma prende il primo
nominativo che incontra nella tabella user.
Scusa, mi tocca dirti di provare su it.comp.software.database.
E facci sapere...

Sono io quello che ti aveva risposto in precedenza :-)
Forse potresti usare un tabella temporanea, piů o meno cosě:
    mysql > CREATE TEMPORARY TABLE tmp(user INT(2), category VARCHAR(16),
voto INT(2));
    mysql > INSERT INTO tmp SELECT utenti.user, category, MAX(votes) FROM
utenti, voti WHERE utenti.user=voti.user GROUP BY category;
    mysql> SELECT * FROM tmp, voti WHERE tmp.voto = voti.votes;
    mysql > DROP TABLE tmp;
Provaci: mal che vada non funziona :-)
:) Roberto 

 utenti.user=voti.user GROUP BY utenti.categoria 
questo sarebbe PROPRIO da FAQ...
come già ripetuto troppe volte per le mie stanche dita,
selezionare in questo modo rompe l'integrità stessa dei dati...
ci andrebbero subqueriies ma con mysql devi ricorrere a cicli effettuabili 
da php.
ciao

 da php.
In teoria ce la puň fare anche senza PHP.
Alla pagina 175 del manuale di mySQL c'č esattamente il caso in questione, e
piů o meno noto che č risolto come pensavo (con una TEMPORARY TABLE), ma con
l'aggiunta di un'istruzione LOCK TABLES.
_China

E facci sapere...
Ok, ho provato anche su alt.php.sql (o qlc del genere). Vi
farò sapere.


da php.
Infatti, rsolvevo così, ma l'overhead è spaventoso (anche
perchè tale query è inclusa in una funzione che ne effettua
altre). Credevo che fosse possibile direttamente con una
query ben fatta. Adesso provo con le temporary table.
Saluti.


 query ben fatta.
Aspettiamo con fiducia le subquery anche in mySQL! Ho trovato un'altra
possibilità a pagina 176 del manuale, ma viene sconsigliata dall'autore
stesso. Dalle comunque un'occhiata, hai visto mai.
_China

 ha sentenziato:

Ciao china,
ho letto le pagine del manuale relative ed ho provato (a me
cmq la apgina in questione è la 278). Purtroppo il problema
è lo stesso. Infatti l'esempio si riferiva cmq ad una
singola tabella e non a due diverse come nel mio caso. In
ogni caso, ho risolto con un ciclo ad hoc, affidandomi ad
una nuova tabella (contenente soltanto user e posizione in
categoria) . Posto il codice per chi è  interessato :
//utilizzo una classe per le funzioni mysql ed un file
//esterno contenente una variabile associativa $sort_reset
//che definisce una query di ordinamento rispetto al campo
//settato in $VARS[RB].
$sorted = $VARS[DBH]->db_query( $sort_reset[$VARS[RB]] );
//crank[$row[9]] è un array associativo che incrementa
//rispetto alla categoria contenuta in $row[9].
  while( $row = $VARS[DBH]->db_nextrow($sorted) ) {
    $crank[$row[9]]++;
    $VARS[DBH]->db_query("INSERT INTO wd_temporary VALUES
('$row[0]',".$crank[$row[9]].' )');
  }
//Questa è la query per prelevare tutti quelli che
//presentano crank=1 nella tabella wd_temporary che viene
//svuotata dopo ogni esecuzione della funzione
      $res=$dbh->db_query("SELECT
voti.recv,wd_temporary.user,
users.cat
 FROM
voti,users,wd_temporary WHERE wd_temporary.user=users.user
AND voti.user=wd_temporary.user  AND wd_temporary.crank=1
ORDER BY 
users.cat
");
In pratica si ordina rispetto al campo voti; si effettua un
ciclo scorrendo un array, incrementando una variabile
associativa che tiene conto della categoria (ogni volta che
si incontra un user appartenente ad una data categoria, si
incrementa il contatore), inserisco queste informazioni in
una tabella di appoggio; infine , effettuo una semplice
query per prelevare tutte le righe che presentano crank=1
(primi nella propria categoria).


 categoria) . Posto il codice per chi è  interessato :
Ah, ma sei un pigrone! Ci arrivavi brillantemente da solo e sei venuto qui a
piangere miseria! ;-))
ciao
_China


No no! Questa soluzione è  artificiosa. Io cercavo qualcosa
da fare direttamente in MySQL. Su un NG anglosassone mi
avevano consigliato di usare una subquery, in una forma
lievemente diversa da quella che ho provato. Posterò la
sintassi che mi hanno proposto e se funziona o meno.


In data  6 Jan 2002 21:57:55 GMT, 
mi...@tin.it
 (WEbdOM) ha
sentenziato:
Questa č la query da alt.php.sql :
--------------------------------------------------------
 You want the row having the group-wise maximum of votes,
joining the two
tables by category.
 Something like:
 
SELECT u.category, u.user, v.votes
FROM   utenti u, votes v
WHERE  u.user = v.user
AND    v.votes = (SELECT MAX(votes)
                  FROM   utenti u2, votes v2
                  WHERE  u2.user = v2.user
                  AND    u.category = u2.category)
------------------------------------------------------------------------
Secondo voi? 


 AND    u.category = u2.category)
Se non č cambiato qualcosa in mySQL nell'ultima settimana non funziona, temo
:-)
_China


hahaha!
Forse hai ragione:)


| >Se non è cambiato qualcosa in mySQL nell'ultima settimana non funziona,
temo
| >:-)
| >
| hahaha!
| Forse hai ragione:)
Non funziona la subquery!:
AND    v.votes = (SELECT MAX(votes) FROM [... KTL]
Glie la stanno chiedendo tutti a MySQL (la subquery, intendo). Ma non la
hanno inserita tra i TODO di più immediata realizzazione.
IMHO, questa è una delle più noiose limitazioni di MySQL.