problema con la paginazione | SQL & MySQL

Topic: Pubblico - Composto da 9 Posts di 3 Utenti.

10 Dicembre, 2011 13:03 #1
rodolforizzo76
Utente

rodolforizzo76
Registrato: Dec, 2011
Posts: 47
Offline

Ho un problema con la paginazione dei risultati di una query. prima di esporre il problema faccio un esempio di come funziona la paginazione, che consiste nel creare due query, la prima che conta i risultati e la seconda che li estrae per mostrarli nella pagina.

Esempio di una pagina funzionante:

1 - La prima query (quella che conta i risultati):

1// PRIMA QUERY
2$count = mysql_query("SELECT COUNT(*) FROM images WHERE image_username = '$pittore' ORDER BY image_id ASC");
3$res_count = mysql_fetch_row($count)

2 - La parte php:

 1// NUMERO TOTALE DEI RECORDS
 2$tot_records = $res_count[0];
 3
 4// RISULTATI PER PAGINA (SECONDO PARAMETRO DI LIMIT)
 5$per_page = 12;
 6
 7// NUMERO TOTALE DI PAGINE
 8$tot_pages = ceil($tot_records / $per_page);
 9
10// PAGINA CORRENTE
11$current_page = (!$_GET['page']) ? 1 : (int)$_GET['page'];
12
13// PRIMO PARAMETRO DI LIMIT
14$primo = ($current_page -1) * $per_page;

3 - infine la query che recupera i risultati:

1// RECUPERO LE MINIATURE
2$query_limit = mysql_query("SELECT * FROM images WHERE image_username = '$pittore' ORDER BY image_id ASC LIMIT $primo, $per_page")
3  or die(mysql_error());
4while ($result = mysql_fetch_array($query_limit)) {
5        extract($result);
6        .....
7        }

e alla fine includo il file che gestisce la paginazione:

1// INCLUDO IL FILE CONTENENTE LA PAGINAZIONE
2include("paginazione_1.php");
3echo '<div class="paginazione">'. $paginazione .'</div>';

il file paginazione1.php è il seguente:

 1<?php
 2
 3$paginazione = "Pagine totali: " . $tot_pages . "
 4[";
 5for($i = 1; $i <= $tot_pages; $i++) {
 6if($i == $current_page) {
 7$paginazione .=' - '. $i;
 8} else {
 9$paginazione .= '<a href="?pittore='. $pittore .'&page='. $i .'" title="Vai alla pagina'. $i .'">'.' - '. $i .'</a>';
10}
11}
12$paginazione .= ' - ]';
13
14?>

Perchè la paginazione funzioni le due query devono contenere la medesima clausola WHERE, se questa è prevista dallo script.

Ora il mio problema è questo, ho la seguente query:

1SELECT i.image_thumb_link, u.nome, u.cognome, u.username, u.id  FROM  images i INNER JOIN dl_user u ON i.image_username = u.username ORDER BY RAND()) AS tmp1 GROUP BY username ORDER BY id DESC

che funziona benissimo, ma non riesco a creare la prima query (quella che conta il numero di risultati) per poi poter implementare la paginazione.

Ho provato cosi:

1SELECT COUNT(*) FROM (SELECT i.image_thumb_link, u.nome, u.cognome, u.username, u.id  FROM  images i INNER JOIN dl_user u ON i.image_username = u.username ORDER BY RAND()) AS tmp GROUP BY username ORDER BY id DESC

Ma così facendo mi conta i record di ogni pittore e non il numero totale di risultati restituiti dalla query.

???


Beh, eh... no, non esattamente. È... ah, è molto complicato come caso. Un mucchio di input e output. Una quantità di informazioni, e un mucchio di elementi da considerare. Ho una quantità di elementi da tenere presente. Fortunatamente io rispetto un regime di droghe piuttosto rigido per mantenere la mente, diciamo, flessibile...
-- The big Lebowski --

10 Dicembre, 2011 16:00 #2
re-verse
Moderatore

re-verse
Registrato: Jul, 2008
Posts: 312
Offline

Sarò sincero... non ci ho capito molto... ma se ti serve sapere quanti record avrai per ogni pittore, la query

1SELECT COUNT(*) AS numero_immagini FROM images WHERE image_username = '$pittore'
dovrebbe andare bene


Salvatore DC

La mente è come un paracadute: funziona solo se si apre. A.Einstein.

10 Dicembre, 2011 16:01 #3
fuser
Utente

fuser
Registrato: Aug, 2011
Posts: 86
Offline

Mamma mia, che accrocchio! :) Te lo dico con simpatia, non offenderti.

Prima di tutto togli l'ORDER BY da tutte le query che devono solo fare un conteggio dei risultati: MySQL le ignora, e se per caso non le ignora perde tempo inutilmente.

La tua query è un po' stranda: usi una GROUP BY, ma questo ha senso solo se usi delle funzioni aggreganti (max, min, count...). Non capisco perchè lo fai; se è per avere il campo username univoco, usa la DISTINCT piuttosto.

Per la query che conta i record, fai semplicemente questo:
SELECT count(*) FROM (copia qui dentro l'altra select pari pari);
Non aggiungere nessuna GROUP BY in fondo.

10 Dicembre, 2011 16:18 #4
rodolforizzo76
Utente

rodolforizzo76
Registrato: Dec, 2011
Posts: 47
Offline

il problema è che il GROUP BY alla fine poi determina il numero di risultati che compaiono nella pagina. A me non serve sapere quanti record avrò per ogni pittore (con la prima query raggruppo tutti i record di un pittore e ne mostro solo uno a caso)

Adesso che ci penso forse posso provare contando i pittori totali, presenti nel database che poi sarebbe anche il numero esatto dei restituiti

la paginazione andrebbe messa in questa pagina qui:

http://www.painteronline.org/pittori.php


Beh, eh... no, non esattamente. È... ah, è molto complicato come caso. Un mucchio di input e output. Una quantità di informazioni, e un mucchio di elementi da considerare. Ho una quantità di elementi da tenere presente. Fortunatamente io rispetto un regime di droghe piuttosto rigido per mantenere la mente, diciamo, flessibile...
-- The big Lebowski --

10 Dicembre, 2011 16:20 #5
rodolforizzo76
Utente

rodolforizzo76
Registrato: Dec, 2011
Posts: 47
Offline

@re-verse
Scommetto che ti sei pentito di avermi detto "Passa a trovarci ogni tanto" :)


Beh, eh... no, non esattamente. È... ah, è molto complicato come caso. Un mucchio di input e output. Una quantità di informazioni, e un mucchio di elementi da considerare. Ho una quantità di elementi da tenere presente. Fortunatamente io rispetto un regime di droghe piuttosto rigido per mantenere la mente, diciamo, flessibile...
-- The big Lebowski --

10 Dicembre, 2011 16:47 #6
rodolforizzo76
Utente

rodolforizzo76
Registrato: Dec, 2011
Posts: 47
Offline

penso che ho risolto, contando il numero di pittori presenti nel db ottengo il numero totale esatto che serve alla prima query per determinare la paginazione.

Resta da vedere cosa succede se un pittore si registra e non carica nessuna immagine. Forse potrebbe indurre qualche errore nella paginazione.

Sarebbe utile riuscire a contare solo i pittori che hanno inserito almeno un immagine.


Beh, eh... no, non esattamente. È... ah, è molto complicato come caso. Un mucchio di input e output. Una quantità di informazioni, e un mucchio di elementi da considerare. Ho una quantità di elementi da tenere presente. Fortunatamente io rispetto un regime di droghe piuttosto rigido per mantenere la mente, diciamo, flessibile...
-- The big Lebowski --

11 Dicembre, 2011 10:25 #7
re-verse
Moderatore

re-verse
Registrato: Jul, 2008
Posts: 312
Offline

non preoccuparti, anzi, siamo qui per questo ;) ...
rispondo a tutte e due le domande:
la prima, sulla group by: se ci fai caso, nella query che ti ho suggeritò non c'è ne' group by ne' order by... perché in realtà, in questo caso, non ti servoro. A te serve un numero, il numero di opere pubblicate da un autore.

Seconda domanda, vorresti poter filtrare, tra gli autori, quelli che hanno pubblicato almeno un'opera: in questo caso ti viene in aiuto la clausola HAVING o addirittura puoi stabilirlo nella WHERE, dipende dai casi... tu in quale query vuoi filtrare gli autori con almeno un'opera pubblicata?


Salvatore DC

La mente è come un paracadute: funziona solo se si apre. A.Einstein.

11 Dicembre, 2011 14:06 #8
rodolforizzo76
Utente

rodolforizzo76
Registrato: Dec, 2011
Posts: 47
Offline

Ciao Salvatore, penso che non mi sono spiegato bene.


la prima, sulla group by: se ci fai caso, nella query che ti ho suggeritò non c'è ne' group by ne' order by... perché in realtà, in questo caso, non ti servoro. A te serve un numero, il numero di opere pubblicate da un autore.

in verità, in questo caso, non mi serve sapere il numero di opere pubblicate da ogni autore ma il numero esatto di risultati che
verranno restituiti. Questo per poter gestire la paginazione.

E il numero esatto di risultati che verranno restituiti consiste nel numero totali di pittori, ma solo di quelli che hanno inserito almeno un quadro. (tu dirai: Ma se uno si registra poi mette anche almeno un quadro! - invece no, capita anche che uno si registra e poi non inserisce nessun quadro..).

Per il momento ho risolto con questa query: (probabilmente sarà deleterea e nociva! magari dopo 10 volte che viene eseguita esplode il computer.. però al momento pare che funziona.). É questa (la prima query, quella per la paginazione):

1SELECT COUNT(*) FROM(SELECT COUNT(image_link) AS numero_pittori FROM images, dl_user WHERE images.image_username = dl_user.username AND dl_user.cognome LIKE '$iniziale%' GROUP BY username) AS totale

poi dopo viene la seconda query (quella che mi hai suggerito tu ma leggermente modificata - ho aggiunto la clausola WHERE cognome LIKE '$iniziale%' e LIMIT $primo, $per_page - per la paginazione dei risultati):

1SELECT * FROM (SELECT i.image_thumb_link, u.nome, u.cognome, u.username, u.id  FROM  images i INNER JOIN dl_user u ON i.image_username = u.username ORDER BY RAND()) AS tmp1 WHERE cognome LIKE '$iniziale%' GROUP BY username ORDER BY id DESC LIMIT $primo, $per_page"

Che mi conta solo i pittori con almeno 1 immagine inserita.
Se hai un suggerimento per migliorare la prima query dimmelo che la modifico. Se pensi che puo andare bene la lascio così.

Una cosa che potremmo ancora mettere a posto è la query dell'altro post, quella per la ricerca, che non siamo riusciti ancora a ottimizzare come vorrei ma che comunque può andare bene anche così com'è.

E comunque ci tengo a ringraziarti ancora per le soluzioni che mi hai mandato senza le quali sarei ancora in alto mare! Anche la guida presente nella sezione php che mi hai linkato è ottima.

Insomma un gran bel forum! Complimenti a tutti.


Beh, eh... no, non esattamente. È... ah, è molto complicato come caso. Un mucchio di input e output. Una quantità di informazioni, e un mucchio di elementi da considerare. Ho una quantità di elementi da tenere presente. Fortunatamente io rispetto un regime di droghe piuttosto rigido per mantenere la mente, diciamo, flessibile...
-- The big Lebowski --

11 Dicembre, 2011 19:03 #9
re-verse
Moderatore

re-verse
Registrato: Jul, 2008
Posts: 312
Offline

Beh... scoppiare il computer dici? naa! stai tranquillo che c'è molto di peggio in giro ;) ... per la ricerca direi che meglio degli indici full-text non puoi fare, almeno che non ci siano esigenze estremamente specifiche.

Per sapere il numero di record darei un'occhiata qui ;) http://www.php.net/manual/en/function.mysql-num-rows.php


Salvatore DC

La mente è come un paracadute: funziona solo se si apre. A.Einstein.

Condividi su:

Loggati o Registrati per replicare