2008-09-18 13 views
21

Estoy ejecutando una consulta SQL en SQL Server 2005, y además de consultar 2 columnas de la base de datos, también me gustaría devolver una columna de números aleatorios junto con ellos. He intentado esto:¿Cómo devuelvo números aleatorios como una columna en SQL Server 2005?

select column1, column2, floor(rand() * 10000) as column3 
from table1 

que funciona un poco, pero el problema es que esta consulta devuelve el mismo número aleatorio en cada fila. Es un número diferente cada vez que ejecuta la consulta, pero no varía de una fila a otra. ¿Cómo puedo hacer esto y obtener un nuevo número aleatorio para cada fila?

+0

Tener un vistazo a mi respuesta, la respuesta ha marcado correcto es incorrecto (usted pidió números entre 0 y 10000) e ineficiente. –

+0

Entonces ... votaste por la pregunta porque no te gusta la respuesta que elegí? –

+0

He aceptado tu respuesta, porque es objetivamente mejor (aunque Adam también hizo lo que yo necesitaba). Sin embargo, quiero enfatizar que las preguntas no se deben rechazar (o subir) en base a las respuestas adjuntas. Por favor vote basado en los méritos de la pregunta. –

Respuesta

40

Me doy cuenta de que esta es una publicación anterior ... pero no necesita una vista.

select column1, column2, 
    ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as column3 
from table1 
+0

¿Qué tal si tomas esta respuesta? Eliminaré la mía y agregaré el mod al tuyo –

+0

. También doy este a + 1 :) –

+0

Esta pregunta/respuesta también puede ser valiosa: versión más corta de lo anterior: http://stackoverflow.com/a/9039661/47226 –

1

Es necesario utilizar una UDF

primera:

CREATE VIEW vRandNumber 
AS 
SELECT RAND() as RandNumber 

en segundo lugar:

CREATE FUNCTION RandNumber() 
RETURNS float 
AS 
    BEGIN 
    RETURN (SELECT RandNumber FROM vRandNumber) 
    END 

prueba:

SELECT dbo.RandNumber(), * 
FROM <table> 

encima tomado de Jeff's SQL Server Blog

1

Para SQLServer, hay un par de opciones.
1. Un bucle while para actualizar una columna vacía con un número aleatorio en un momento
2. Un .NET Asamblea que contiene una función que devuelve un número aleatorio

1

consulta

select column1, column2, cast(new_id() as varchar(10)) as column3 
from table1 
1

Es posible que desee considerar la generación de un UUID en lugar de un número aleatorio usando la función newid. Se garantiza que serán únicas cada vez que se generen, mientras que hay una posibilidad significativa de que se produzca alguna duplicación con un número aleatorio directo (y dependiendo de para qué lo use, podría darle un error fenomenalmente difícil de depurar en un momento posterior)

1

newid() Creo que requiere muchos recursos. Recuerdo probar ese método en una tabla de unos pocos millones de registros y el rendimiento no fue tan bueno como rand().

4

ADVERTENCIA

Adam's answer que implica la vista es muy ineficiente y por muy grandes conjuntos pueden sacar su base de datos durante bastante tiempo, yo recomendaría fuertemente contra el uso sobre una base regular o en situaciones donde necesita poblar tablas grandes en producción.

En su lugar, puede usar this answer.

Prueba:

CREATE VIEW vRandNumber 
AS 
SELECT RAND() as RandNumber 

go 

CREATE FUNCTION RandNumber() 
RETURNS float 
AS 
    BEGIN 
    RETURN (SELECT RandNumber FROM vRandNumber) 
    END 

go 

create table bigtable(i int) 

go 

insert into bigtable 
select top 100000 1 from sysobjects a 
join sysobjects b on 1=1 

go 

select cast(dbo.RandNumber() * 10000 as integer) as r into #t from bigtable 
-- CPU (1607) READS (204639) DURATION (1551) 

go 

select ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 10000 as r into #t1 
from bigtable 
-- Runs 15 times faster - CPU (78) READS (809) DURATION (99) 

Profiler trace:

alt text http://img519.imageshack.us/img519/8425/destroydbxu9.png

Ésta es una prueba de que la materia es bastante aleatorio para números entre 0 a 9999

-- proof that stuff is random enough 
select avg(r) from #t 
-- 5004 
select STDEV(r) from #t 
-- 2895.1999 

select avg(r) from #t1 
-- 4992 
select STDEV(r) from #t1 
-- 2881.44 


select r,count(r) from #t 
group by r 
-- 10000 rows returned 

select r,count(r) from #t1 
group by r 
-- 10000 row returned 
+0

¿Qué tan aleatorios fueron los números en cada caso? – cjk

+0

Confirmaré que para números entre 1 y 10000, mantenga apretada –

+0

respuesta expandida con prueba de que las cosas son aleatorias –

1

Según mis pruebas , la respuesta anterior no genera un valor de 10000 nunca. Esto probablemente no sea un gran problema cuando se genera un azar entre 1 y 10000, pero el mismo algoritmo entre 1 y 5 sería notorio. Agrega 1 a tu mod.

+0

La pregunta no era sobre la generación de números aleatorios en un rango específico. Cualquier número aleatorio haría. 10000 es solo un número arbitrario que utilicé en mi ejemplo de código. –

1

Este fragmento parece proporcionar un sustituto razonable para rand() en el sentido de que devuelve un valor entre 0,0 y 1,0. Utiliza solo los últimos 3 bytes proporcionados por newid(), por lo que la aleatoriedad total puede ser ligeramente diferente a la conversión a VARBINARY y luego a INT y luego modificar a partir de la respuesta recomendada. No he tenido la oportunidad de probar el rendimiento relativo, pero parece lo suficientemente rápido (y lo suficientemente aleatorio) para mis propósitos.

SELECT CAST(SubString(CONVERT(binary(16), newid()), 14, 3) AS INT)/16777216.0 AS R 
3
select RAND(CHECKSUM(NEWID())) 
+0

esto realmente funciona. entiendes mi punto. simple y responde las preguntas directamente. ¡Gracias! – ekkis

1

que utilizar C# para hacer frente a los números al azar. Es mucho más limpio Tengo una función que uso para devolver una lista de números aleatorios y una clave única, luego me uno a la uniqueKey en el número de fila. Como uso C#, puedo especificar fácilmente un rango dentro del cual deben caer los números aleatorios.

Éstos son los pasos para hacer la función: http://www.sqlwithcindy.com/2013/04/elegant-random-number-list-in-sql-server.html

Esto es lo que termina mi consulta pareciéndose:

SELECT 
    rowNumber, 
    name, 
    randomNumber 
FROM dbo.tvfRandomNumberList(1,10,100) 
INNER JOIN (select ROW_NUMBER() over (order by int_id) as 'rowNumber', name from client   
      )as clients 
ON clients.rowNumber = uniqueKey 
Cuestiones relacionadas