Skip site navigation (1) Skip section navigation (2)

Re: Un enregistrement au hasard ?

From: "Daniel Verite" <daniel(at)manitou-mail(dot)org>
To: pgsql-fr-generale(at)postgresql(dot)org
Subject: Re: Un enregistrement au hasard ?
Date: 2008-11-13 12:15:52
Message-ID: c13bedef-0c31-4f1c-8ca9-e2ab0f31f6d3@mm (view raw or flat)
Thread:
Lists: pgsql-fr-generale
	Sébastien Dinot wrote:

> Stephane Bortzmeyer a écrit :
> > L'excellent site StackOverflow a toujours vu un débat sur toute
> > question technique :-)
> >
> > 
http://stackoverflow.com/questions/19412/how-to-request-a-random-row-in 
-sql
> 
> Je viens d'essayer la solution proposée en tête de page en effectuant 
une
> adaptation minimaliste à PostgreSQL :
> 
> SELECT *
>   FROM personne
>  WHERE id_personne >= RANDOM() * ( SELECT MAX(id_personne) FROM 
personne )
>  LIMIT 1;
> 
> Ecrite ainsi, cette requête ne fonctionne pas très bien chez moi.

Cette méthode parait vraiment très mauvaise par rapport au besoin 
d'obtenir une ligne aléatoire. (précision: je ne vois pas la page sur 
stackoverflow car dans l'immédiat le site a l'air HS avec une erreur 
http 503).

Si on essaie d'imaginer comment la requête pourrait être exécutée...
Mettons que sur une première exécution, le random()*max renvoie 500.
Donc on demande ça au moteur SQL:
  SELECT * from personne where id_personne>=500 limit 1;
On peut imaginer que pour trouver le résultat, il se positionne sur une 
page quelque part dans l'index, au début ou ailleurs selon comment il 
est programmé (il peut aussi favoriser une page en cache), il lit une 
valeur de id_personne, et si elle est supérieure il s'arrête là. Aucun 
besoin d'aller plus loin puisqu'un résultat satisfaisant est trouvé et 
qu'il y a un LIMIT 1.

Mettons que sur une deuxième exécution, le random()*max renvoie 400.
Maintenant on demande ça au moteur SQL:
  SELECT * from personne where id_personne>=400 limit 1;
Il se positionne encore sur une page dans l'index, typiquement la même 
qu'avant parce qu'aucune raison de changer, lit une valeur de 
id_personne, trouve la même qu'avant, qui étant supérieure à 500, est a 
fortiori supérieur à 400. Et donc il renvoie à nouveau cette même 
valeur puisqu'elle satisfait au critère.

Et on peut imaginer qu'il sorte comme ça le même résultat N fois de 
suite, sans que ce soit du tout choquant ni improbable. Ca veut juste 
dire que le caractère aléatoire de cette méthode est inexistant :)

-- 
 Daniel
 PostgreSQL-powered mail user agent and storage: 
http://www.manitou-mail.org

In response to

pgsql-fr-generale by date

Next:From: Guillaume LelargeDate: 2008-11-14 17:24:07
Subject: Re: PGXMl?
Previous:From: Sébastien DinotDate: 2008-11-12 23:12:05
Subject: Re: Un enregistrement au hasard ?

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group