Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonjour,
Je souhaite récupérer X enregistrements aléatoires dans une table de ma base de données.
Actuellement, je procède de la sorte :
[lang=php] public function fetchRandomPosts($number) { $result = $this->tableGateway->select( function(Select $select) use ($number) { $select->limit($number); } ); return $result; }
La limite fonctionne, mais je ne trouve pas comment générer un rand() SQL avec Zend.
Connaissez-vous une bonne manière de le faire ?
Merci.
Dernière modification par Thoomaas (23-01-2013 15:11:20)
Hors ligne
Salut, je ne sais pas s'il y a une bonne méthode avec Zend mais ça se fait dans la clause Order By de cette façon :
[lang=sql]SELECT * FROM MA_TABLE ORDER BY RAND() LIMIT 10
Faut savoir que c'est très très très gourmand est dégueulasse comme requête. On doit pouvoir faire autrement mais je n'ai pas trouvé donc à utiliser avec parcimonie. Cette requête va récupérer l'ensemble des résultats de ta table même avec un limit et va te retourner aléatoirement les 10 premiers résultats. Contrairement à ce qu'on pense limit ne limite pas la requête SQL mais seulement le retour
Hors ligne
Mettre un colonne de type int unique dans la table et gérer l'alléatoire avant l'exécution de la requête.
[lang=sql] SELECT * FROM MA_TABLE WHERE MA_COLONNE_INT IN (1,124,56124, ....) ORDER BY MA_COLONNE_INT
Si tu mets un index sur MA_COLONNE_INT ça prendra très peux de ressource.
Hors ligne
Ca peux fonctionner aussi mais ceci implique de connaitre tous les ID de la table avant car si l'ID a été supprimé ou n'existe pas les résultats ne seront pas bon.
Hors ligne
Tout dépend de ta base de données.
Si c'est MySql tu peux faire ça
public function fetchRandomPosts($number) {
$result = $this->tableGateway->select(
function(Select $select) use ($number) {
$select->limit($number)->order('RAND()');
}
);
return $result;
}
Hors ligne
Merci à tous pour vos diverses réponses.
Je suis assez étonné que Zend ne propose pas ce genre d'options. Peut-être que l'explication d'Orkin sur la "dégueulassité" de la requête en est la cause.
Ayant une base MySQL, j'ai souhaité opter pour la solution de Juch, mais j'obtiens l'erreur suivante :
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'RAND`(`)' in 'order clause'
Et sinon, récupérer l'identifiant minimal et le maximal dans la table, tirer au sort des ids compris dans l'intervalle de ces deux valeurs (en PHP), puis récupérer les informations des posts tirés dans la base -> cela devrait être moins gourmand et plus efficace, non ?
On aura certes deux requêtes (celle pour min/max puis celle pour les infos) contrairement à une (avec un simple Rand()) mais les requêtes seront plus légères.
Qu'en pensez-vous ?
Merci !
Hors ligne
et bien écoute moi c'est ce que j'utilise personnellement quand je veux faire un rand()
apres tout dépend de ta version de ZF, tu utilises laquelle ?
Hors ligne
Thoomaas a écrit:
Et sinon, récupérer l'identifiant minimal et le maximal dans la table, tirer au sort des ids compris dans l'intervalle de ces deux valeurs (en PHP), puis récupérer les informations des posts tirés dans la base -> cela devrait être moins gourmand et plus efficace, non ?
On aura certes deux requêtes (celle pour min/max puis celle pour les infos) contrairement à une (avec un simple Rand()) mais les requêtes seront plus légères.
Qu'en pensez-vous ?
Merci !
Je ne voudrais pas trop m'avancer mais de mémoire c'est moins gourmand de faire les deux requêtes tel que tu le dis plutôt qu'un rand. Le problème de cette solution le voici :
Exemple :
Tu as une table qui a comme id min : 1 et comme id max : 15. Pour une raison X ou Y tu as supprimé les id 8 et 9. Tu as donc toujours le même minimum et maximum pour les id mais au lieu d'en avoir 15 tu n'en as plus que 13. Tu veux récupérer 10 éléments au hasard dans cette table, lorsque tu vas faire ton rand entre 1 et 15 la fonction va te retourner les 10 id aléatoire. Le problème est que si tu tombes sur les id 8 et 9 ta requête retournera que 8 éléments au lieu de 10
Donc même si la solution est dégueulasse de mettre un rand dans le order by c'est malheureusement une des meilleures solution mais la requête est vraiment plus gourmande.
Sinon tu peux essayer de récupérer tous les éléments de la table (s'il n'y a pas trop de jointures ça devrait pas être trop long) et via PHP en récupérer que 10 aléatoirement.
Concernant ton problème de requête, pour ma part j'utilise doctrine et j'ai du l'écrire en SQL pure sans passer par du DQL (Doctrine Query Language)
Hors ligne
Thoomaas a écrit:
Bonjour,
Je souhaite récupérer X enregistrements aléatoires dans une table de ma base de données.
Actuellement, je procède de la sorte :Code:
[lang=php] public function fetchRandomPosts($number) { $result = $this->tableGateway->select( function(Select $select) use ($number) { $select->limit($number); } ); return $result; }La limite fonctionne, mais je ne trouve pas comment générer un rand() SQL avec Zend.
Connaissez-vous une bonne manière de le faire ?
Merci.
Je ne me suis pas penché sur la récupération aléatoire, mais il y a quelque chose de sûr : ce code récupère toujours les mêmes enregs, c'est juste la limite qui sera aléatoire...
Hors ligne
C'est normal c'est ce qu'il cherche à faire ...
Hors ligne
Bon à mon avis ça doit venir de ta version de ZF car je n'ai aucun problème.
Essaie ça :
$select->order( array( new Zend_Db_Expr('RAND()') ) );
Hors ligne
@Orkin : Je vais me pencher sur ta dernière proposition, de tout récupérer puis d'en choisir un certain nombre en PHP. C'est vrai que si LIMIT ne fait que "cacher" des résultats, autant faire le traitement RAND en PHP. Merci !
@Juch : J'utilise la dernière version disponible via composer (2.*).
Hors ligne
ah ok j'avais pas vu que tu étais en ZF2 au temps pour moi
donc faut utiliser Zend\Db\Sql\Expression
voici l'exemple pour ton problème
[lang=php]public function fetchRandomPosts($number) { $result = $this->tableGateway->select( function(Select $select) use ($number) { $select->limit($number)->order( array( new Expression('RAND()') ) ); } ); return $result; }
En considérant qu'il restait un problème il n'y a pas longtemps et pas sur que ça soit corriger sur ta release.
cf. https://github.com/zendframework/zf2/pull/3017
Dernière modification par Juch (23-01-2013 14:37:06)
Hors ligne
En effet, ça marche beaucoup mieux comme ça. Je vais procéder, pour l'instant, de cette façon.
Je garde quand même de côté la remarque d'Orkin concernant la lourdeur de la requête et j'aviserais après avoir effectué plusieurs tests.
Merci à tous, c'est donc résolu !
Hors ligne
Sinon tu as : http://php.net/manual/fr/function.array-rand.php
pour le faire en php
Hors ligne
Oui, je ferais les traitements en PHP si je vois que le SQL est trop gourmand ;-) !
Hors ligne