[SOLUCIONADO] Actualizar con número aleatorio | mysql

Iniciado por elshotta, Octubre 12, 2020, 01:09:50 AM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Octubre 12, 2020, 01:09:50 AM Ultima modificación: Octubre 13, 2020, 08:10:15 PM por AXCESS
Hola a todos,
lo que pasa es que estoy haciendo una aplicación de un sorteo y necesito tener un numero de ganadores X.
lo que hago es insertar los números de las personas que entran al sorteo según entran (1,2,3,4,...), y cuando es el momento de hacer el sorteo utilizo un update rand y me funciona bien, pero se me repiten los números osea aparecen varios ganadores con números repetidos puse un unique a la tabla pero da igual me tira error de numero duplicado, será que alguien en el foro sabrá como solucionar esto?
los códigos son
Código: mysql
CREATE PROCEDURE sorteo(IN turnos int(100)
UPDATE sorteo
SET turno = FLOOR(rand() * turnos) + 1


Gracias de antemano

Creo que puede que lo estés enfocando mal. Igual deberías hacer algo asi como seleccionar los usuarios con un limite, que sería tu número de ganadores, y sacar los datos ordenarlos por rand();

Creo que el buen enfoque sería algo así:
Código: php

Select * from usuarios order by rand() limit X;

Donde X sería el número de gnadores. Si necesitas updatear algún campo usas el resultado de eso como entrada de los que vas a updatear.

Lo siento, no contesto dudas por MP, si tienes dudas las planteas en el foro.

Octubre 12, 2020, 05:56:07 AM #2 Ultima modificación: Octubre 13, 2020, 02:05:34 PM por DtxdF
@No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Debería considerar usar una función pseudo-aleatoria que le proporcione su lenguaje de programación o el mismo sistema operativo donde está ahora mismo, pero lo relevante aquí es que debe tener una fuerte entropía para impedir volver a tener números repetidos.

No sé qué lenguaje esté usando, supondré que PHP, pero le dejo otros ejemplos por si acaso le sirve y también para comprender cómo funcionan una capa más abajo de la abstracción.

Usar una formula como esta FLOOR(RAND()*(b-a)+a) significa que deseas obtener un número en un rango de a a b pero no significa que se pueda repetir en algunas iteraciones más, por lo que es mejor usar funciones como las siguiente:

Código: php
<?php
$bytes = random_bytes(5);
var_dump(bin2hex($bytes));

?>


Esto imprimiría:

Código: text
string(10) "89429d753c"


Recuerde que está en hexadecimal la salida para que se pueda mostrar de una forma clara para nosotros los humanos, pero debe convertir esos bytes en enteros válidos para poder ser usados.

Se usa la función bin2hex, como le mencioné, para mostrar en un formato claro para nosotros, pero para usar enteros, unpack podría ayudarle:

Código: php
<?php
$bytes = random_bytes(5);
var_dump(unpack("n", $bytes));

?>


Eso resultaría en:

Código: php
array(1) {
  [1]=>
  int(40219)
}


Aquí unas referencias de la misma documentación:
*- No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
*- No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Si está usando Python le recomiendo la librería secrets que se encarga de ser un envoltorio entre la función generadora de su sistema operativo:

Código: python
import secrets

print(secrets.token_hex(5))


Imprimiría:

Código: text
660fb8c6e6


Referencia:
*- No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Y por último usando un archivo especial:

Código: c
#include <stdio.h>
#include <stdlib.h>

#define MAX_BUFF_SIZE 6

void gen_random(char *buff, int l) {
int i;
FILE *gen;

gen = fopen("/dev/urandom", "rb");
while (l--)
buff += sprintf(buff, "%02x", getc(gen));

buff -= l*2;

fclose(gen);

}

int main(void) {
char buff[MAX_BUFF_SIZE*2];

gen_random(buff, MAX_BUFF_SIZE);
printf("%s\n", buff);

return EXIT_SUCCESS;

}


Imprimiría:

Código: text
5510aeb233ce


Referencia:
*- No tienes permitido ver los links. Registrarse o Entrar a mi cuenta/dev/random

~ DtxdF
PGP :: <D82F366940155CB043147178C4E075FC4403BDDC>

~ DtxdF

Gracias por responder,
no es una tarea de la clase de base de datos osea tengo que hacerla en mysql :s
gracias

Octubre 13, 2020, 07:52:43 AM #4 Ultima modificación: Octubre 13, 2020, 02:08:16 PM por DtxdF
@No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

En general, entonces la formula que te mencioné está bien, pero no tanto considerando que se pueden volver a repetir los números en muchas iteraciones, por lo que debes poner la confianza en el rango, mientras más largo sea, mejor.

Actualizado.

Reflexionando un poco su cuestión; necesita entonces un número aleatorio, que será usado para un torneo o sorteo (es irrelevante), pero el problema es que no es susceptible que no se repita, además el problema debe er solucionado usando puramente SQL.

Bueno, no es necesario cambiar casi nada, entonces usamos un dato único, como el identificador de usuario que mayormente es numérico, es único o es una clave primaria (por ende no se repite), por lo que usaremos de nuevo nuestra formula: FLOOR(RAND()*(b-a)+a) para generar número aleatorios de a a b, sin embargo, el problema es que en la iteraciones se pueden repetir; hagamos algo simple, vamos a sumarlo con el identificador de usuario que es único, por lo que no se volvería a repetir:

Código: mysql
SELECT FLOOR(RAND()*(1000-50)+50)+id FROM users;


Las variables aquí son:

A = 50
B = 1000
La tabla = users
La columna = id

Espero le ayude y comente si funcionó o no.

~ DtxdF
PGP :: <D82F366940155CB043147178C4E075FC4403BDDC>

~ DtxdF

Esa si me ha funcionado, gracias!!
Ya puedes dar por solucionado la pregunta
Gracias  ;D :D