mysql query, sum(qualcosa), order by sum(qualcosa). E' possibile?

gandalf1959

Utente Attivo
21 Nov 2013
208
1
18
Buongiorno a tutti,
ho una tabella che contiene i dati degli isccritti a lezioni di cucina e mi serve ottenere un elenco delle lezioni e per ciascuna lezione il totale degli iscritti. Naturalmente da una pagina .php
La query che utilizzo è
Codice:
$query = ("SELECT *, sum(postiprenotati) FROM `utentiscuola` GROUP BY id_lezione ORDER BY id_lezione");
E funziona.
Però non riesco ad ordinare la lista in base alla somma degli utenti. E' possibile?
Mettendo ...ORDER BY sum(postiprenotati) non funziona, naturalmente...
Qualche suggerimento?
Grazie
 
Prova così
PHP:
$query = "SELECT * FROM utentiscuola WERE sum ORDER BY  * ASC";
 
scusami, ma la query del primo post non può funzionare, perché,

nella clausola group by devono essere elencati tutti gli elementi non raggruppati,

indicando "*" nella select, si presuppone che debba restituire più colonne, che giustappunto non sono elencate nella group by

supponendo che la tabella contenga solo le colonne "id_lezione" e "postiprenotati", ti restituirebbe, per via dell'asterisco
esattamente le due colonne (dettaglio massimo) e poi dovrebbe fare la somma, di cosa ?

quando si usa la clausola group by, è normale specificare, al posto dell'asterisco, l'elenco delle colonne che definiscono il raggruppamento e poi le colonne raggruppate,
le colonne che definiscono il raggruppamento sono poi elencate nella clausola group by
Codice:
$query = "SELECT id_lezione, sum(postiprenotati) FROM utentiscuola GROUP BY id_lezione ORDER BY id_lezione";
Codice:
$query = "SELECT id_lezione, sum(postiprenotati) FROM utentiscuola GROUP BY id_lezione ORDER BY sum(postiprenotati), id_lezione";
 
Ho capito, grazie. In effetti adesso ho esattamente il risultato che mi aspettavo.
E ho imparato qualcos'altro, come sempre!
Nel frattempo ho un'altra cosa che non capisco e ne approfitto:
Oltre al codice della lezione, devo visualizzarne il titolo, che si trova in un'altra tabella (che si chiama calendario). I codici lezione sono unici.
All'interno del ciclo while, dopo aver estratto dalla query di cui sopra il codice lezione e la somma relativa, ho messo una semplice query
Codice:
$query1 = ("SELECT titolo FROM calendario WHERE id_lezione = '$lezione'");
che necessariamente mi restituisce un solo record, quindi ho scritto:
Codice:
$tito = mysql_query($query1);
    $riga = mysql_fetch_assoc($tito);
    $titolo = $riga['titolo'];
Poi chiudo il php, aggiungo la riga della tabella da popolare, riapro php, metto l'incremento di $i e chiudo il ciclo while.
Mi aspettavo di avere l'lenco che ottenevo prima con l'aggiunta nell'apposita casella del titolo della lezione.
Invece PRIMA mi visualizza tutti i titoli, POI mi popola la tabella con i due valori di prima (cod lezione e somma utenti)
Come mai? Dove ho sbagliato?
Ecco il codice completo:
Codice:
<table width=100%>
    <tr>
        <td width="20%">Cod. Lezione</td><td width="25%">Titolo Lezione</td><td width="10%">Iscritti</td><td width="45%">&nbsp;</td>
       
    </tr>
    <tr>
        <td colspan="4"><hr></td>
    </tr>


<?

include 'connect.php';

$query = ("SELECT *, sum(postiprenotati) FROM utentiscuola GROUP BY id_lezione ORDER BY sum(postiprenotati), id_lezione");
$lezanno = mysql_query($query);
$numero = mysql_num_rows($lezanno);

//stampo l'anno di riferimento

echo "<p align = 'center'>2016</p>";

$i = 0;
while ($i < $numero) {
    $lezione = mysql_result($lezanno, $i, "id_lezione");
    $somma = mysql_result($lezanno, $i, 'sum(postiprenotati)');

    // Recupero il titolo della lezione

    $query1 = ("SELECT titolo FROM calendario WHERE id_lezione = '$lezione'");
    $tito = mysql_query($query1);
    $riga = mysql_fetch_assoc($tito);
    $titolo = $riga['titolo'];

    ?>

    <tr>
        <td><? echo $lezione; ?></td><? echo $titolo; ?></td><td><? echo $somma; ?></td><td></td>
    </tr>

    <?

    $i++;

}
    ?>

   




</table>
Grazie per l'ulteriore suggerimento
 
ciao
prova una cosa del genere (al massimo non funziona)
PHP:
<?php
//....
//intanto potresti dare un alias alla somma
$query = "SELECT id_lezione, sum(postiprenotati) AS totale FROM utentiscuola GROUP BY id_lezione ORDER BY totale, id_lezione";
$ris=mysql_query($query);
//poi semplifica
if(mysql_num_rows($ris)> 0){
    while($riga=mysql_fetch_array($ris)){
        $id_lezione=$riga['id_lezione'];
        $posti_prenotati=$riga['totale'];
        $query1 = "SELECT titolo FROM calendario WHERE id_lezione = $id_lezione";
        //attento immagino che l'id_lezione sia un numero intero: non ci vanno gli apici
        $ris1=mysql_query($query1);
        $riga1=mysql_fetch_array($ris1);
        $titolo=$riga1['titolo'];
        echo "<tr>";
        echo "<td>$titolo</td><td>$posti_prenotati</td>";
        echo "</tr>";
    }
}else{
    echo "non ci sono dati";
}
//.....
?>
inoltre, penso che marino51 si sia dimenticato di dirtelo, abbandona le vecchie istruzioni php mysql obsolete e passa alle nuove mysqli
 
ciao
dimenticavo io forse potresti semplificare ulteriormente usando una join(al massimo anche questa non funziona)
PHP:
<?php
//....
//dando i vari alias
$query = "SELECT ut.sum(postiprenotati) AS totale, ca.titolo AS tit 
            FROM utentiscuola AS ut, calendario AS ca
            WHERE ut.id_lezione=ca.id_lezione
            GROUP BY ud.id_lezione ORDER BY totale, ut.id_lezione";
$ris=mysql_query($query);
//poi semplifica
if(mysql_num_rows($ris)> 0){
    while($riga=mysql_fetch_array($ris)){
        $posti_prenotati=$riga['totale'];
        $titolo=$riga1['tit'];
        echo "<tr>";
        echo "<td>$titolo</td><td>$posti_prenotati</td>";
        echo "</tr>";
    }
}else{
    echo "non ci sono dati";
}
//.....
?>
meno chiamate al db si fanno e meno risorse si sprecano
 
Grazie. Adesso devo uscire, poi metto in pratica i suggerimenti.
Una domanda ignorante: mySql a mysqli possono convivere o devo aggiornare tutte le procedure che ho scritto?
 
puoi usare,
Codice:
"
SELECT us.id_lezione, sum(us.postiprenotati), cal.titolo
FROM utentiscuola us
LEFT JOIN calendario cal ON us.id_lezione = cal.id_lezione
GROUP BY us.id_lezione
ORDER BY sum(us.postiprenotati), us.id_lezione
";
se sei certissimo che ci sia sempre almeno un titolo in calendario per ogni id_lezione esistente in "utentiscuola", puoi semplificare con
Codice:
"
SELECT us.id_lezione, sum(us.postiprenotati), cal.titolo
FROM utentiscuola us, calendario cal
where us.id_lezione = cal.id_lezione
GROUP BY us.id_lezione
ORDER BY sum(us.postiprenotati), us.id_lezione
";
 
ciao
non non possono convivere, però è semplice modificare senza lavorare troppo
le differenze sostanziali sono nella connessione
$con=mysqli_connect("host","user"."pass","nome_db");
poi quella $con va messa nella mysqli_query di select/update/delete
$ris=mysqli_query($conn, "SELECT.....");
nellle altre basta aggiungere una i es. mysql_num_rows diventa mysqli_num_rows
tutto questo per semplificare perchè poi mysqli ha altre caratteristiche (es supporta la programmazione ad oggetti), ma per ora è sufficiente
 
ciao
dimenticavo io forse potresti semplificare ulteriormente usando una join(al massimo anche questa non funziona)
PHP:
<?php
//....
//dando i vari alias
$query = "SELECT ut.sum(postiprenotati) AS totale, ca.titolo AS tit
            FROM utentiscuola AS ut, calendario AS ca
            WHERE ut.id_lezione=ca.id_lezione
            GROUP BY ud.id_lezione ORDER BY totale, ut.id_lezione";
$ris=mysql_query($query);
//poi semplifica
if(mysql_num_rows($ris)> 0){
    while($riga=mysql_fetch_array($ris)){
        $posti_prenotati=$riga['totale'];
        $titolo=$riga1['tit'];
        echo "<tr>";
        echo "<td>$titolo</td><td>$posti_prenotati</td>";
        echo "</tr>";
    }
}else{
    echo "non ci sono dati";
}
//.....
?>
meno chiamate al db si fanno e meno risorse si sprecano

In effetti non funziona... anche correggendo GROUP BY ut... invece di ud :-)
Se ho capito bene, la select in questione dice: seleziona dalla tabella utentiscuola, che chiameremo ut e dalla tabella calendario che chiameremo ca, da ut fai la somma di postiprenotati e da ca seleziona il titolo, che chiameremo tit, dove il campo id_lezione di ut e il campo id_lezione di ca sono uguali, poi raggruppa e ordina.
Giusto? Non ho mai utilizzato una query così articolata.
Sembrerebbe tutto corretto, in effetti, ma mi dà poi un errore sulla riga dove c'e'
Codice:
if (mysql_num_rows($ris) > 0) {
che recita:
"Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in /htdocs/public/www/backoffice/iscritti_per_lezione.php on line 65 Non ci sono dati".
In pratica dovrebbe leggere il campo id_lezione da utentiscuola, trovare la corrispondenza in calendario da cui prende il titolo corrispondente, e poi fare la somma, raggruppare e ordinare, ma non trova nulla.
Scusa la mia ignoranza, ma dov'è l'errore? BTW il tuo snippet di prima funzionava perfettamente, quindi per ora uso quello. La domanda qui è solo per cercare di capire e imparare.
Grazie
 
ciao
l'ud è un errore di battitura, comunque è una join implicita (quella di marino è una join esplicita).
intanto usa lo script che funziona, per il secondo prova a mettere un var_dump
PHP:
<?php
//.....
$ris=mysql_query($query);
var_dump($ris);
//poi semplifica
if(mysql_num_rows($ris)> 0){
//......
?>
se da false la query non viene eseguita e quindi è facile che ci sia un errore nella querystringa

dimenticavo: il tuo ragionamento è giusto
 
la query di Borgo contiene un errore, modifica così, "sum(ut.postiprenotati)"
ed è simile (identica) alla seconda query del mio ultimo post

ti suggerisco però di non usarla perché, se per qualsiasi motivo, non è presente il titolo nella tabella calendario,
il record non ti viene estratto mentre la "left join" te lo estrae con titolo = null

se vuoi una visuale sulle join, guarda qui
http://www.codeproject.com/KB/database/Visual_SQL_Joins/Visual_SQL_JOINS_orig.jpg
 
mmm non c'e' verso che funzioni con alias e join...
Adesso pero' devo andare avanti con il resto delle cose da aggiungere. Riprenderò più avanti con lo studio...
Intanto grazie
 

Discussioni simili