Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 13-04-2008
DarkDudae DarkDudae is offline
Miembro
 
Registrado: abr 2006
Posts: 94
Poder: 19
DarkDudae Va por buen camino
Orden aleatorio con Rand() Ineficaz

Hola a todos,

estoy intentando sacar un listado aleatorio de filas con un SELECT en firebird.

He estado haciendo pruebas con la función Rand():

Código SQL [-]
SELECT CAMPO1, CAMPO2, CAMPO3 FROM MITABLA
ORDER BY RAND()


Aparentemente, funciona, pero nada más lejos de la realidad. Cada vez que ejecutas el query sin cerrar la aplicación, parece que la función RAND hace su cometido, y ordena las filas aleatoriamente. Pero es falso. Si cierras la aplicación, y la vuelves a abrir, se obtiene exactamente la misma ordenación.

Ejemplo: Ejecuto mi aplicación y uso el SELECT anterior y me da este orden:

3-4-2-1

Si vuelvo a ejecutar el Query nuevamente me da un orden diferente:

1-3-4-2


Y así sucesivamente...

Si cierro la aplicación y vuelvo a ejecutar el SELECT, obtendré nuevamente la misma ordenación: 3-4-2-1 , luego 1-3-4-2 ...



Si podeis arrojar algo de luz a este asunto, os estaría muy agradecido.

Saludos
Responder Con Cita
  #2  
Antiguo 13-04-2008
Avatar de xEsk
[xEsk] xEsk is offline
Miembro Premium
 
Registrado: feb 2006
Posts: 454
Poder: 19
xEsk Va por buen camino
Eso es porque debes inicializar el rand().

Es como en Delphi, antes de usar el random, debes llamar al "randomize()".

El problema, es que ahora mismo no se si existe alguna función en Firebird que haga esto, es cuestión de buscarlo por internet.

Saludos.
Responder Con Cita
  #3  
Antiguo 13-04-2008
DarkDudae DarkDudae is offline
Miembro
 
Registrado: abr 2006
Posts: 94
Poder: 19
DarkDudae Va por buen camino
Cita:
Empezado por xEsk Ver Mensaje
Eso es porque debes inicializar el rand().

Es como en Delphi, antes de usar el random, debes llamar al "randomize()".

El problema, es que ahora mismo no se si existe alguna función en Firebird que haga esto, es cuestión de buscarlo por internet.

Saludos.
Eso fue lo primero que pensé, pero parece ser que no existe nada por el estilo (al menos yo no lo he sabido encontrar)

Como solución provisional, antes de ejecutar el select normal, ejecuto otros selects limitados a dos únicos registros con un único campo en su parámetro de búsqueda. Esta consulta, la ejecuto entre 1 y 100 veces (con la función random propia de delphi). Así al menos me aseguro de que el random maneje 100 posibilidades de inicio distintas.

Es una solución bastante cutre, ya que es ejecutar a veces hasta 100 veces una consulta inútil, pero al menos me sirve para inicializar la consulta cuasi-aleatoriamente.

Si conocéis alguna otra solución mejor...

Saludos
Responder Con Cita
  #4  
Antiguo 13-04-2008
Avatar de xEsk
[xEsk] xEsk is offline
Miembro Premium
 
Registrado: feb 2006
Posts: 454
Poder: 19
xEsk Va por buen camino
Una solución que se me ocurrió fue reemplazar la función rand() del Firebird por otra creada por mi (importarla en forma de UDF), pero después pensé, que es muy raro que lleve un random y no un randomize, así que mire manualmente en el fichero ib_udf2.sql que lleva el Firebird, y efectivamente, he encontrado el srand().

Te copio su descripción:
Código SQL [-]
/*****************************************
 *
 *  s r a n d
 *
 *****************************************
 *
 * Functional description:
 *  Seeds the random number generator using
 *  the current time and returns the first
 *  pseudo-random number (between 0 and 1)
 *  in the new sequence.
 *
 * Note:
 *  Two srand() calls performed within a second
 *  will return the same value.
 * 
 *****************************************/
DECLARE EXTERNAL FUNCTION srand 
  RETURNS DOUBLE PRECISION BY VALUE
  ENTRY_POINT 'IB_UDF_srand' MODULE_NAME 'ib_udf';

Saludos.
Responder Con Cita
  #5  
Antiguo 15-04-2008
DarkDudae DarkDudae is offline
Miembro
 
Registrado: abr 2006
Posts: 94
Poder: 19
DarkDudae Va por buen camino
Ante todo, muchas gracias. Funciona perfectamente.

Cuando buscaba una solución, también indagué en la documentación del firebird, pero cuando leí que el srand() era la antigua función rand() que ha sido sustituida recientemente por la rand() actual para evitar que la semilla arrojase valores aleatorios iguales cuando se ejecutaban diversas llamadas en el mismo segundo, la dejé en el olvido:

Cita:
UDFs Added and Changed
IB_UDF_rand() vs IB_UDF_srand()
IB_UDF_lower
UDFs added or enhanced in Firebird 2.0's supplied libraries are:
IB_UDF_rand() vs IB_UDF_srand()
F. Schlottmann-Goedde
In previous versions, the external function rand() sets the random number generator's starting point based on the current time and then generates the pseudo-random value.
srand((unsigned) time(NULL));
return ((float) rand() / (float) RAND_MAX);

The problem with this algorithm is that it will return the same value for two calls done within a second.
To work around this issue, rand() was changed in Firebird 2.0 so that the starting point is not set explicitly. This ensures that different values will always be returned.
In order to keep the legacy behaviour available in case somebody needs it, srand() has been introduced. It does exactly the same as the old rand() did.
No obstante, para mis necesidades, las limitaciones del antiguo rand() no son tales. En fin, cada función tiene sus pros y sus contras.

Un saludo!
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Numero aleatorio de productos principiante22 Impresión 6 04-03-2008 01:24:08
Alguien sabe como usar la Función Rand() en firebird DANNY777 Firebird e Interbase 2 26-01-2008 16:19:17
Select aleatorio JBalda Firebird e Interbase 11 27-06-2007 20:28:23
Orden aleatorio al 7o digito!!! jdattoli Tablas planas 1 20-10-2005 18:15:09
Presentar ordern aleatorio en un Select aerosB4 Firebird e Interbase 4 16-08-2004 12:53:21


La franja horaria es GMT +2. Ahora son las 04:23:59.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi