View Full Version : [MySQL/PHP] SELECT di tutti i result tranne primo e ultimo
Thunder29
17-02-2011, 13:14
Salve,
sapete dirmi per caso come si faccia a fare una query che prenda tutti i risultati tranne il primo e l'ultimo? Va bene sia una query mysql che un workaround in PHP.
Grazie,
Flavio
bobbytre
17-02-2011, 13:52
prova cosi:
//--
$dbconn = new mysqli($hostname,$username,$password,$database);
$result = $dbconn->query("SELECT count(*) FROM my_table");
$max = $result->fetch_array();
$max = $max[0]-2;
$result = $dbconn->query("SELECT * FROM my_table LIMIT 1,$max ;");
john_revelator
17-02-2011, 21:02
select * from tabella
where id not in (select min(id) from tabella union select max(id) from tabella)
order by id
Thunder29
18-02-2011, 09:14
Vi ringrazio!! :)
black_wizard
18-02-2011, 14:11
non facevi prima a prendere tutti i valori dalla query e poi con il php escludevi a video il primo e l'ultimo?
alemoppo
19-02-2011, 14:30
non facevi prima a prendere tutti i valori dalla query e poi con il php escludevi a video il primo e l'ultimo?
Direttamente da mysql è meglio.. sia in termini di prestazioni, sia in termini di codice (il sorgente PHP viene più corto).
Ciao!
black_wizard
19-02-2011, 19:35
sicuro che è meglio in termini di prestazioni?
questo è un argomento che mi ha sempre interessato.
Non è meglio chiamare meno volte possibile o chiamare una volta sola il database per interrogare una tabella anzichè farlo più volte in una stessa pagina?
alemoppo
19-02-2011, 19:47
Certamente!. Infatti questo:
select * from tabella
where id not in (select min(id) from tabella union select max(id) from tabella)
order by id
È un'unica query :D
Ciao!
black_wizard
19-02-2011, 19:54
la query è unica ma in realtà è come se facesse 2 chiamate al database essendoci 2 select.
cmq io parlavo in termini generali nella domanda di prima.
Forse è meglio che ti faccio un esempio...
per esempio abbiamo 100 o 1000 news
id_news(tipo int), titolo_news(varchar), categoria_news(tipo int)
e poi una tabella con le categorie
id_categoria(tipo int), titolo_categoria(varchar)
ora io di solito faccio una sola query per le categorie e mi salvo i valori in un array in php e poi una query per le news e confronto i 2 id con array_keys_exists per ottenere il nome della categoria.
Però c'è sempre il metodo che tu hai citato sopra...quello di usare un'unica query per fare entrambe le cose.
Quale è quello più produttivo?
khelidan1980
19-02-2011, 21:09
Certamente!. Infatti questo:
select * from tabella
where id not in (select min(id) from tabella union select max(id) from tabella)
order by id
È un'unica query :D
Ciao!
che si una unica query non vuol dire niente, in qui il db deve ordinare per trovare il min, poi per trovare il max e in più fare una union e poi deve fare i confronti per risolvere il not in, su tanti dati è potenzialmente devastante
Supdario
19-02-2011, 21:24
Però c'è anche da dire che la colonna "id" è molto probabilmente (anzi, sicuramente) definita come indice e chiave primaria, quindi la ricerca all'interno di quella colonna è velocissima dato che i dati sono in cache.
Inoltre quando si esegue una query, essa viene automaticamente ottimizzata dall'ottimizzatore interno, cosa che ovviamente non succede nel caso di query multiple.
alemoppo
19-02-2011, 22:35
Non ho resistito :D
Sorgente di prova:
<?php
$db=mysql_connect("localhost","alemoppo", "");
if(!mysql_select_db("my_alemoppo",$db))
die('errore selezione db');
$array = array();
/*Tramite PHP (unset)*/
$start0 = microtime(true);
$ris = mysql_query('SELECT * FROM registrati order by id',$db);
while($row = mysql_fetch_row($ris))
$array[] = $row[1];
unset($array[0],$array[count($array)]);
$end0 = microtime(true);
unset($array);
/*tramite php (pop + shift)*/
$start1 = microtime(true);
$ris = mysql_query('SELECT * FROM registrati order by id',$db);
while($row = mysql_fetch_row($ris))
$array[] = $row[1];
array_shift($array);
array_pop($array);
$end1 = microtime(true);
unset($array);
/*tramite mysql*/
$start2 = microtime(true);
$ris = mysql_query('SELECT * FROM registrati where id not in (select min(id) from registrati union select max(id) from registrati) order by id',$db);
while($row = mysql_fetch_row($ris))
$array[] = $row[1];
$end2 = microtime(true);
unset($array);
echo 'Risultati:<br>';
echo ($end0-$start0).'<br>';
echo ($end1-$start1).'<br>';
echo ($end2-$start2);
mysql_close($db);
?>
Risultati:
0.00034189224243164
0.00032901763916016
0.00031590461730957
---
0.00038290023803711
0.00032997131347656
0.00031614303588867
---
0.0003509521484375
0.00037193298339844
0.00036811828613281
---
0.00034999847412109
0.00037002563476562
0.00031590461730957
---
0.00052499771118164
0.00056695938110352
0.00053501129150391
---
0.00034999847412109
0.00037503242492676
0.00032591819763184
---
0.00052213668823242
0.00056099891662598
0.00049090385437012
Eseguito su altervista; quindi il carico dei server varia secondo degli utenti presenti sui siti del server. Quando avrò tempo, proverò in locale, per avere test un po più veritiero :D
p.s: i record della tabella sono 118 (116 eliminanto la prima e l'ultima).
Conclusioni:
A parte il modo con shift + pop, più o meno ci impiegano lo stesso tempo. A volte è più rapido utilizzare mysql; a volte PHP.
Da notare, però, che il modo con unset() restituisce un array che inizia dalla posizione [1].. quindi bisognerebbe rimapparlo, impiegando più tempo :)
Ciao!
black_wizard
20-02-2011, 01:34
c'è anche il metodo
/*Tramite PHP (if e mysql_num_rows)*/
$start0 = microtime(true);
$i=1;
$ris = mysql_query('SELECT * FROM registrati order by id',$db);
$num = mysql_num_rows($ris);
while($row = mysql_fetch_row($ris)){
if (($i>1)AND ($i<$num))
$array[] = $row[1];
$i++;
}
$end0 = microtime(true);
unset($array);
in base ai test eseguiti con il codice tuo più questo ultimo..risulta che il migliore è il mio.
Non avevo mai pensato di eseguire questi test per risolvere i miei dubbi.
Cmq ovviamente l'ho fatto eseguire un paio di volte...su una tabella con 303 record in locale e su un hosting aruba da 496 record.
Ho notato per lo più che la 3° funzione fatta interamente con una sola query..la sua velocità varia mentre la prima è quella peggiore di tutte.
Cmq bene o male si può affermare che per cose tipo queste del soggetto del thread..usare una sola query o il 2° metodo o il 4° porta allo stesso risultato.
Bisogna veder su record un pò più grandicelli..o più tabelle messe in relazione.
bobbytre
20-02-2011, 02:06
Con i test del post precedente vince quello che esegue un unica query
50.000 elementi e test ripetuti 10 volte
test_1 : Media : 3.6415376186371
test_2 : Media : 3.7319422721863
test_3 : Media : 3.5299593448639
<?php
$hostname = ;
$username = ;
$password = ;
$database = ;
#------------------------------------------------------------------------------#
#
#
#
function test_inizializza()
{
global $hostname;
global $username;
global $password;
global $database;
$link = mysql_connect($hostname,$username,$password);
mysql_select_db($database);
$q = "
CREATE TABLE IF NOT EXISTS `tabella1`
(
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`data1` varchar(1024) NOT NULL,
`data2` text NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
";
mysql_query($q);
for($i=0;$i<50000;$i++)
{
$ss1= str_shuffle('1d6115f8257ca25c1c39642835be2c0a');
$ss2 = str_shuffle('1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a1d6115f8257ca25c1c39642835be2c0a');
$q = "INSERT INTO tabella1 VALUES ('', '$ss1', '$ss2');";
mysql_query($q);
}
mysql_close();
exit();
}
#------------------------------------------------------------------------------#
#
#
#
function test_1()
{
global $hostname;
global $username;
global $password;
global $database;
$link = mysql_connect($hostname,$username,$password);
mysql_select_db($database);
$results = mysql_query("SELECT * FROM tabella1 ORDER BY id;");
while($row = mysql_fetch_row( $results ))
$array[] = $row[1];
unset($array[0],$array[count($array)]);
mysql_close();
}
#------------------------------------------------------------------------------#
#
#
#
function test_2()
{
global $hostname;
global $username;
global $password;
global $database;
$link = mysql_connect($hostname,$username,$password);
mysql_select_db($database);
$results = mysql_query("SELECT * FROM tabella1 ORDER BY id;");
while($row = mysql_fetch_row( $results ))
$array[] = $row[1];
array_shift($array);
array_pop($array);
mysql_close();
}
#------------------------------------------------------------------------------#
#
#
#
function test_3()
{
global $hostname;
global $username;
global $password;
global $database;
$link = mysql_connect($hostname,$username,$password);
mysql_select_db($database);
$results = mysql_query("SELECT * FROM tabella1 where id not in (select min(id) from tabella1 union select max(id) from tabella1) order by id;");
while($row = mysql_fetch_row( $results ))
$array[] = $row[1];
mysql_close();
}
#------------------------------------------------------------------------------#
#
#
#
$c = 3;
// --
$res = array();
$x = 0;
for($i=0;$i<$c;$i++)
{
$time_start = microtime(true);
test_1();
$time_end = microtime(true);
$time = $time_end - $time_start;
$x += $time;
}
echo "test_1 : Media : ".$x/$c."\n";
// --
$res = array();
$x = 0;
for($i=0;$i<$c;$i++)
{
$time_start = microtime(true);
test_2();
$time_end = microtime(true);
$time = $time_end - $time_start;
$x += $time;
}
echo "test_2 : Media : ".$x/$c."\n";
// --
$res = array();
$x = 0;
for($i=0;$i<$c;$i++)
{
$time_start = microtime(true);
test_3();
$time_end = microtime(true);
$time = $time_end - $time_start;
$x += $time;
}
echo "test_3 : Media : ".$x/$c."\n";
alemoppo
20-02-2011, 09:59
c'è anche il metodo[...]
Vero!. Non mi era nemmeno venuto in mente. Quel metodo pensandoci, dovrebbe essere velocissimo!...
Con i test del post precedente vince quello che esegue un unica query
50.000 elementi e test ripetuti 10 volte
test_1 : Media : 3.6415376186371
test_2 : Media : 3.7319422721863
test_3 : Media : 3.5299593448639
[...]
Poi, come detto nel mio post, il primo test restituisce un array che non parte da 0... bisognerebbe far scorrere tutti gli elementi alla chiave precedente... facendo impiegare più tempo e... chissà che forse non sia più lento del test 2 :D
---
Comunque, l'avevo detto che era più veloce utilizzare mysql!. Più si fanno procedimenti in mysql, meglio è!... Il (mio) problema, però, è che non lo conosco bene.. e di norma eseguo le varie cose tramite PHP, anche se andrebbero effettuate con mysql :muro:
Ciao!
black_wizard
20-02-2011, 12:02
nei prox giorni proverò con più tabelle messe in relazione per capire quale metodo è il migliore.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.