¿Cómo seleccionar al azar filas en SQL?


226

Estoy usando MSSQL Server 2005. En mi base de datos, tengo una tabla "customerNames" que tiene dos columnas "Id" y "Nombre" y aprox. 1,000 resultados.

Estoy creando una funcionalidad en la que tengo que elegir 5 clientes al azar cada vez. ¿Alguien puede decirme cómo crear una consulta que obtenga 5 filas al azar (Id y Nombre) cada vez que se ejecute la consulta?


Aleatorio no es un requisito común para una base de datos, me sorprendió encontrar un enlace para algunos SQL
Paxic

2
Depende de la cantidad de aleatoriedad que desee. Ver: msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx para comparar NEW_ID versus RAND ()
Shannon Severance

Respuestas:


639
SELECT TOP 5 Id, Name FROM customerNames
ORDER BY NEWID()

Dicho esto, todo el mundo parece venir a esta página para obtener una respuesta más general a su pregunta:

Seleccionar una fila aleatoria en SQL

Seleccione una fila aleatoria con MySQL:

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

Seleccione una fila aleatoria con PostgreSQL:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

Seleccione una fila aleatoria con Microsoft SQL Server:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

Seleccione una fila aleatoria con IBM DB2

SELECT column, RAND() as IDX 
FROM table 
ORDER BY IDX FETCH FIRST 1 ROWS ONLY

Seleccione un registro aleatorio con Oracle:

SELECT column FROM
( SELECT column FROM table
ORDER BY dbms_random.value )
WHERE rownum = 1

Seleccione una fila aleatoria con sqlite:

SELECT column FROM table 
ORDER BY RANDOM() LIMIT 1

3
+1 por publicar las respuestas directamente en SO en lugar de vincular a un sitio externo (como la respuesta aceptada) que podría haber disminuido cuando los futuros usuarios examinen esta pregunta.
Ray Zhou

17
¿Esto se vuelve muy costoso en tablas grandes, donde cada fila obtiene un número aleatorio, y luego se ordena un gran conjunto de números aleatorios no indexados?
Andrey

Esto es quizás obvio para la mayoría de las personas, pero no lo fue para mí ... la siguiente consulta no obtendrá un nuevo valor aleatorio para cada fila: update tbl_vouchers set tbl_UsersID = (select top(1) id from tbl_Users order by NEWID()) - editar: no puedo hacer que el formato funcione en los comentarios :(
Mir

Usted genio! Te odio tanto porque no vi esto hasta que me fui y escribí una consulta increíblemente larga con subconsultas y números de fila.
greenkode

55
Advertencia: para grandes bases de datos, este método tendrá un mal rendimiento. ¿Te imaginas el tiempo que llevará generar un valor aleatorio para cada fila si la base de datos tiene un millón de entradas? Puede obtener más información y una mejor alternativa aquí .
Francis Ngueukam


11

En caso de que alguien quiera una solución PostgreSQL:

select id, name
from customer
order by random()
limit 5;

Esta respuesta es buena para PostgreSQL, no necesita el límite.
aliasbody

9

Quizás este sitio sea ​​de ayuda.

Para aquellos que no quieren hacer clic:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

2
al menos debería haber reemplazado 1 con 5 :)
roman m


5

Si tiene una tabla con millones de filas y le preocupa el rendimiento, esta podría ser una mejor respuesta:

SELECT * FROM Table1
WHERE (ABS(CAST(
  (BINARY_CHECKSUM
  (keycol1, NEWID())) as int))
  % 100) < 10

https://msdn.microsoft.com/en-us/library/cc441928.aspx


Tenga en cuenta que esto seleccionará aproximadamente el 10% de las filas de la tabla. Si necesita seleccionar un número exacto de filas, o al menos N filas, este enfoque no funcionará.
LarsH

4

Esta es una pregunta antigua, pero intentar aplicar un nuevo campo (ya sea NEWID () o ORDER BY rand ()) a una tabla con un gran número de filas sería prohibitivamente costoso. Si tiene ID únicos incrementales (y no tiene agujeros) será más eficiente calcular el X # de ID que se seleccionará en lugar de aplicar un GUID o similar a cada fila y luego tomar el X # superior de.

DECLARE @minValue int;
DECLARE @maxValue int;
SELECT @minValue = min(id), @maxValue = max(id) from [TABLE];

DECLARE @randomId1 int, @randomId2 int, @randomId3 int, @randomId4 int, @randomId5 int
SET @randomId1 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId2 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId3 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId4 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId5 = ((@maxValue + 1) - @minValue) * Rand() + @minValue

--select @maxValue as MaxValue, @minValue as MinValue
--  , @randomId1 as SelectedId1
--  , @randomId2 as SelectedId2
--  , @randomId3 as SelectedId3
--  , @randomId4 as SelectedId4
--  , @randomId5 as SelectedId5

select * from [TABLE] el
where el.id in (@randomId1, @randomId2, @randomId3, @randomId4, @randomId5)

Si quisiera seleccionar muchas más filas, buscaría llenar una #tempTable con una ID y un montón de valores rand () y luego usar cada valor rand () para escalar a los valores min-max. De esa manera no tiene que definir todos los parámetros @ randomId1 ... n. He incluido un ejemplo a continuación utilizando un CTE para completar la tabla inicial.

DECLARE @NumItems int = 100;

DECLARE @minValue int;
DECLARE @maxValue int;
SELECT @minValue = min(id), @maxValue = max(id) from [TABLE];
DECLARE @range int = @maxValue+1 - @minValue;

with cte (n) as (
   select 1 union all
   select n+1 from cte
   where n < @NumItems
)
select cast( @range * rand(cast(newid() as varbinary(100))) + @minValue as int) tp
into #Nt
from cte;

select * from #Nt ntt
inner join [TABLE] i on i.id = ntt.tp;

drop table #Nt;

@Protiguo, la edición que propuso rompió la selección aleatoria. El uso de min () y max () aplicado a la tabla dbo.Tally64k no le permitiría al usuario seleccionar una fila con un ID de paquete> 65556.
RIanGillis

El cambio de nombre de la tabla fue simplemente un artefacto de la prueba. El nombre real de la tabla no importa, siempre que se use la tabla correcta. min () y max () se pueden consultar en una consulta en lugar de dos, que es lo que estaba tratando de mostrar.
El

@Protiguo Ah, ahora veo que estaba confundido porque usaste el 0-65k cuando hiciste el min-max pero no más tarde. Después de su edición más reciente, realmente quería preguntarle sobre las implicaciones de rendimiento de los cambios que realizó, ya que el ajuste del rendimiento es uno de mis intereses y las decisiones aparentemente sin sentido, como qué lado del signo de igualdad coloca usted, pueden tener un impacto significativo. - ¿Se aplicaría lo mismo a las 5 llamadas SET @ randomId ##? ¿O es diferente porque no está SELECCIONANDO DE una tabla real?
RIanGillis

No estoy seguro de entender tu pregunta. ¿Se pregunta por qué hay 5 SET en lugar de solo 1 SELECT @ id1 = rand (), @ id2 = rand () ..? Esto se debe a que múltiples llamadas a un rand () en 1 instrucción producirán el mismo resultado, de ahí el SET separado. (rand () en SQL Server es una función determinista, creo). Supongo que 1 select vs 5 set está en el rango de nanosegundos en términos de rendimiento.
El

4
SELECT * FROM TABLENAME ORDER BY random() LIMIT 5; 

Antigua pregunta, pero esta respuesta no me funcionó en Oracle.
Oso

SELECT * FROM (SELECT * FROM table ORDER BY DBMS_RANDOM.VALUE) WHERE rownum <número; @Bear prueba esto
Narendra

3

He encontrado que esto funciona mejor para Big Data.

SELECT TOP 1 Column_Name FROM dbo.Table TABLESAMPLE(1 PERCENT);

TABLESAMPLE(n ROWS) or TABLESAMPLE(n PERCENT) es aleatorio pero necesita agregar el TOP n para obtener el tamaño de muestra correcto.

El uso NEWID()es muy lento en mesas grandes.


0

Como expliqué en este artículo , para barajar el conjunto de resultados de SQL, debe usar una llamada de función específica de la base de datos.

Tenga en cuenta que ordenar un gran conjunto de resultados utilizando una función ALEATORIA puede resultar muy lento, así que asegúrese de hacerlo en pequeños conjuntos de resultados.

Si tiene que barajar un gran conjunto de resultados y limitarlo después, es mejor usar algo como OracleSAMPLE(N) o el TABLESAMPLEen SQL Server o PostgreSQL en lugar de una función aleatoria en la cláusula ORDER BY.

Entonces, suponiendo que tengamos la siguiente tabla de base de datos:

ingrese la descripción de la imagen aquí

Y las siguientes filas en la songtabla:

| id | artist                          | title                              |
|----|---------------------------------|------------------------------------|
| 1  | Miyagi & Эндшпиль ft. Рем Дигга | I Got Love                         |
| 2  | HAIM                            | Don't Save Me (Cyril Hahn Remix)   |
| 3  | 2Pac ft. DMX                    | Rise Of A Champion (GalilHD Remix) |
| 4  | Ed Sheeran & Passenger          | No Diggity (Kygo Remix)            |
| 5  | JP Cooper ft. Mali-Koa          | All This Love                      |

Oráculo

En Oracle, debe usar la DBMS_RANDOM.VALUEfunción, como se ilustra en el siguiente ejemplo:

SELECT
    artist||' - '||title AS song
FROM song
ORDER BY DBMS_RANDOM.VALUE

Al ejecutar la consulta SQL mencionada anteriormente en Oracle, obtendremos el siguiente conjunto de resultados:

| song                                              |
|---------------------------------------------------|
| JP Cooper ft. Mali-Koa - All This Love            |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |

Observe que las canciones se enumeran en orden aleatorio, gracias a la DBMS_RANDOM.VALUEllamada a la función utilizada por la cláusula ORDER BY.

servidor SQL

En SQL Server, debe usar la NEWIDfunción, como se ilustra en el siguiente ejemplo:

SELECT
    CONCAT(CONCAT(artist, ' - '), title) AS song
FROM song
ORDER BY NEWID()

Al ejecutar la consulta SQL mencionada anteriormente en SQL Server, obtendremos el siguiente conjunto de resultados:

| song                                              |
|---------------------------------------------------|
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |
| JP Cooper ft. Mali-Koa - All This Love            |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |

Observe que las canciones se enumeran en orden aleatorio, gracias a la NEWIDllamada a la función utilizada por la cláusula ORDER BY.

PostgreSQL

En PostgreSQL, debe usar la randomfunción, como se ilustra en el siguiente ejemplo:

SELECT
    artist||' - '||title AS song
FROM song
ORDER BY random()

Al ejecutar la consulta SQL mencionada anteriormente en PostgreSQL, obtendremos el siguiente conjunto de resultados:

| song                                              |
|---------------------------------------------------|
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| JP Cooper ft. Mali-Koa - All This Love            |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |

Observe que las canciones se enumeran en orden aleatorio, gracias a la randomllamada a la función utilizada por la cláusula ORDER BY.

MySQL

En MySQL, debe usar la RANDfunción, como se ilustra en el siguiente ejemplo:

SELECT
  CONCAT(CONCAT(artist, ' - '), title) AS song
FROM song
ORDER BY RAND()

Al ejecutar la consulta SQL mencionada anteriormente en MySQL, obtendremos el siguiente conjunto de resultados:

| song                                              |
|---------------------------------------------------|
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| JP Cooper ft. Mali-Koa - All This Love            |

Observe que las canciones se enumeran en orden aleatorio, gracias a la RANDllamada a la función utilizada por la cláusula ORDER BY.


0

Si está utilizando una tabla grande y desea acceder al 10 por ciento de los datos, ejecute el siguiente comando: SELECT TOP 10 PERCENT * FROM Table1 ORDER BY NEWID();

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.