[MySQL-Résolu] select x derniers enregistrements - par ordre croissant

Bonjour,
j’aimerai sélectionner les x derniers enregistrements d’une table. Lorsque le tri est décroissant, je n’ai aucune difficulté mais en tri croissant, je ne sais pas comment faire car ça sélectionne les x premiers et non les x derniers). J’ai bien tenté d’écrire limit -x mais ça ne marche pas. J’ai aussi tenté de regarder dans la doc de mysql mais elle est indigeste.

Voici ma requète avec x = 50 et tri décroissant.

SQL
[color=blue;font-weight:bold]SELECT[/color] * FROM `srw_wars` WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` DESC LIMIT 0, 50;

ptet en faisant un truc dans le style de ça :

SQL
[color=blue;font-weight:bold]SELECT[/color] * FROM `srw_wars` WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` ASC LIMIT COUNT(id)-x, COUNT(id);
?
SQL
[color=blue;font-weight:bold]SELECT[/color] * FROM `srw_wars` AS T WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` ASC LIMIT (COUNT(T.id)-50), 50;

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘(COUNT(T.id)-50), 50’ at line 1 :neutre:

Je dis peut-etre une betise mais ça me parait normal en fait.

Dans ta requete, tu mets un limit à 0, 50

Donc tu lui demande de partir de 0 et de prendre les 50 enregistrement suivant.
Donc forcément en mode décroissant ça marche, mais en mode croissant… il va prendre les 50 premiers.

Il faudrait faire un count de l’ensemble, enlever 50 et faire un limit XX (ou XX représente le chiffre du count moins les 50 derniers enregistrement)
C’est ce que benj a essayé de traduire en requete je pense.
Moi je me serais fais chier à faire deux requetes (ou une requete + sous-requete) une qui compte et l’autre qui selectionne :wink:

Bon j’ai aussi essayé ceci :

SQL
[color=blue;font-weight:bold]SELECT[/color] *, count(T.id) AS N FROM `srw_wars` AS T WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` ASC LIMIT (N-50), 50;

Mais erreur : ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘(N-50), 50’ at line 1

Etant donné que je récupère les résultats dans php, je ne peux faire “qu’une requète par requète” (je me comprend).
C’est vrai que je pourrai faire une requète au préable pour déterminer le nombre d’entrées… Je vais tenter mais j’aimerai faire un minimum de requètes (j’en ai déjà énormément)…

Je comprend tout à fait le principe de “une requete par requete”, j’utilise la meme méthode faute d’etre un expert en SQL :wink:
Essais avec une requete supplémentaire… c’est ce que j’aurais fait pour avoir le count global moins les cinquantes dernier enregistrement.
Je reconnais que c’est “lourd” mais ayant oublié une grande partie de mes cours SQL de l’époque, je ferais pas mieux :lol:

et si tu fais ça :

SQL
[color=blue;font-weight:bold]SELECT[/color] *, count(T.id)-50 AS N FROM `srw_wars` AS T WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` ASC LIMIT N, 50;
?
SQL
[color=blue;font-weight:bold]SELECT[/color] *, count(T.id)-50 AS N FROM `srw_wars` AS T WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date`ASC LIMIT N, 50;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘N, 50’ at line 1

SQL
[color=blue;font-weight:bold]SELECT[/color] *, (count(T.id)-50) AS N FROM `srw_wars` AS T WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` ASC LIMIT N, 50;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘N, 50’ at line 1

Ce qu’il a pas l’air d’aimer c’est que l’on mette autrechose qu’un nombre dans la limite.
En attendant, je fais deux requètes mais j’aimerai ne pas rester sur une bète requète. Voici un petit extrait de mon php en attendant (il fonctionne).

	$count = q('SELECT COUNT(id) AS `n` FROM `srw_'.strtolower($what).'` WHERE `v` = \''.$v.'\' AND `user` = \''.$joueur.'\';', $con);
	$count = mysql_fetch_array($count);
	$count = $count['n'];
	if ($nbr == 'all') $limit = '';
	else if (preg_match('!^[0-9]+$!', $nbr)) $limit = ' LIMIT '.((($count-$nbr) > 0) ? ($count-$nbr) : 0).', '.$nbr;
	else $error = true;
	if (!$error) {
  $q = 'SELECT * FROM `srw_'.strtolower($what).'` WHERE `v` = \''.$v.'\' AND `user` = \''.$joueur.'\' ORDER BY `'.strtolower($tri).'` ASC'.$limit.';';
  //echo $q;
  $q = q($q, $con) or die(mysql_error());
  $n = mysql_num_rows($q);
  if ($n == 0) return '<p>Rien. </p>';
  else {

En lisant la doc MySQL j’ai vu qu’il était possible de créer des variables temporaires utilisables dans les requètes. Je vais aller refaire un tour la dedans… :sarcastic:
Peut etre que Sans-Pseudo passera par là. :pt1cable:

Arrive toujours pas. :??:

alors on va se la finement :

SET @skip=SELECT count(`srw_wars.id`)-50 from `srw_wars`; SET @numrows=50;
PREPARE func FROM 'SELECT * FROM `srw_wars` AS T WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` ASC LIMIT ?, ?';
EXECUTE func USING @skip, @numrows;

C’est moche mais bon.

SandRock> ce que tu veux en fait, c’est prendre les 50 derniers résultats, et les trier de manière croissante?

Et ça :

SQL
([color=blue;font-weight:bold]SELECT[/color] * FROM `srw_wars` WHERE `v` = '19-1' AND `user` = '1' ORDER BY `date` DESC LIMIT 50) ORDER BY date ASC

(normalement, c’est censé fonctionner)

Oui, c’est ça que je souhaite faire.
J’ai essayé quelque chose de similaire à ta proposition avant de poster ici.
L’idée est donc dans un premier temps de sélectionner les 50 derniers par ordre descendant puis de les réordonner.
La première partie fonctionne mais lorsque je refais le tri, la requète plantouille et prend tous les enregistrements par ordre descendant.

Petit screen : http://img142.imageshack.us/img142/7783/mysqlerreursrw11up.th.jpg

Moi aussi je m’étais dit que ça fonctionnerai mais étrangement non…
Pour info je suis sous MySQL 5.0.20a-nt.

Essaye de faire une union voir où est le problème.

Sinon envoie un bug pour mySQL ?

Saluton,
A ma connaissance, MySQL n’accepte pas de clause ORDER BY dans un sub-select.
Mais je pense qu’il doit y avoir moyen d’obtenir ce que tu veux en demandant à MySQL de numéroter les enregistrements par à une jointure réflexive sur la table.
Je vais y réfléchir.

Rien que ça ? C’est quoi une jointure réflexive au juste ? :riva:

Euh faut pas faire quelque chose de trop complexe car il y aura entre 0 et 1000 enregistrements qui pourront être retournés…
Par contre je ne comprend pas que ça puisse posez autant de problèmes pour une requète aussi simple… Ce qui aurait été bien ça serait de mettre un nombre négatif pour la limite mais c’est trop demander pour MySQL…

Bon moi vais réviser : épreuves de TP pour le bac demain. :frowning:

t’as pas essayé la derniere magouille que j’ai proposé ?

Bien j’ai du mal à faire fonctionner ça en command line. Le problème c’est que j’exploite les résultats avec PHP donc je ne peux faire qu’une seule requète par requète… Même si je tentais avec plusieurs mysql_query(), ça sera encore plus gros que ma solution de remplacement en 2 requètes (une compte, l’autre récup).
Je vais quand même tenter la chose…

Bon finalement, je te suggères de déporter le problème de SQL vers le L4G support ce qui donne, par exemple sous PHP/MySQL.
Voici ce que j’ai testé sur une table d’uen de mes bases en local

<pre>
<?php
error_reporting(E_ALL);
$serveur="~~~~";
$user="~~;
$DBpwd="";
$nomDB="~~~~~~";
$conn=mysql_connect($serveur,$user,$DBpwd)or die(mysql_error());
mysql_select_db($nomDB,$conn)or die(mysql_error());
$sql = "SELECT code, client, date_commande, CONCAT(jourdepart,' ', heuredepart) AS rang FROM commandes 
 ORDER BY rang DESC LIMIT 3";
$req=mysql_query($sql);
$res=array();
while($res[]=mysql_fetch_assoc($req)){}
array_splice($res,-1,1);
$res=array_reverse($res);
print_r($res);
mysql_close();
?>
</pre>

Carrément pas bète de tout mettre dans un array et d’inverser l’ordre ! Adopté !
Merci ! :clap:

PS : PHP risque d’un peu soufrir vu le nombre d’enregistrement mais c’est aps grave, il aime ça !