SQL에서 무작위로 행을 선택하는 방법은 무엇입니까?


226

MSSQL Server 2005를 사용하고 있습니다. 내 데이터베이스에는 "Id"와 "Name"이라는 두 개의 열과 약 2 개의 열이있는 "customerNames"테이블이 있습니다. 결과 1,000 개

매번 5 명의 고객을 무작위로 선택해야하는 기능을 만들고 있습니다. 누구나 쿼리를 실행할 때마다 임의의 5 행 (Id 및 Name)을 얻는 쿼리를 만드는 방법을 말해 줄 수 있습니까?


랜덤은 데이터베이스에 대한 일반적인 요구 사항이 아니며, 일부 SQL에 대한 링크 를 발견 한 것에 놀랐습니다.
Paxic

2
원하는 무작위성에 따라 다릅니다. 참조 : msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx을 RAND () 대 NEW_ID의 비교
섀넌 세브란스

답변:


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

즉, 귀하의 질문에 대한보다 일반적인 답변을 얻으려면 모두이 페이지에 오는 것 같습니다.

SQL에서 임의의 행 선택

MySQL로 임의의 행을 선택하십시오.

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

PostgreSQL로 임의의 행을 선택하십시오.

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

Microsoft SQL Server에서 임의의 행을 선택하십시오.

SELECT TOP 1 column FROM table
ORDER BY NEWID()

IBM DB2로 임의의 행을 선택하십시오.

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

Oracle에서 무작위 레코드를 선택하십시오.

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

sqlite로 임의의 행을 선택하십시오.

SELECT column FROM table 
ORDER BY RANDOM() LIMIT 1

3
향후 사용자가이 질문을 볼 때 다운 될 수있는 외부 사이트 (예 : 허용 된 답변)에 연결하는 대신 SO에 직접 답변을 게시 한 경우 +1
Ray Zhou

17
각 행이 임의의 숫자를 얻은 후 색인화되지 않은 큰 임의의 숫자 세트가 정렬되는 큰 테이블에서 이것이 매우 비싸지 않습니까?
Andrey

이것은 대부분의 사람들에게 아마 분명하다,하지만 ... 다음 쿼리는 각 행에 대한 새로운 임의의 값을받지 않습니다 나에게 분명하지 않았다 : update tbl_vouchers set tbl_UsersID = (select top(1) id from tbl_Users order by NEWID()) - 편집 : 나는 :( 의견 작업에 서식을 얻을 수 없다
미르

천재! 내가 가서 하위 쿼리와 행 번호로 미친 긴 쿼리를 작성할 때까지 이것을 보지 못했기 때문에 나는 당신을 너무 싫어합니다.
greenkode

5
경고 : 큰 데이터베이스의 경우이 방법의 성능이 저하됩니다. 데이터베이스에 백만 개의 항목이있는 경우 각 행에 대해 임의의 값을 생성하는 데 걸리는 시간을 상상할 수 있습니까? 당신은 여기 에 대한 더 많은 정보와 더 나은 대안을 가질 수 있습니다 .
Francis Ngueukam


11

누군가가 PostgreSQL 솔루션을 원할 경우 :

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

이 답변은 PostgreSQL에 적합하며 제한이 필요하지 않습니다.
aliasbody

9

아마 이 사이트가 도움이 될 것입니다.

클릭 연결을 원하지 않는 사람들을 위해 :

SELECT TOP 1 column FROM table
ORDER BY NEWID()

2
적어도 1을 5로 대체해야합니다 :)
로마 m


5

수백만 행의 테이블이 있고 성능에 관심이 있다면 더 나은 대답이 될 수 있습니다.

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

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


이렇게하면 테이블에있는 행의 약 10 %가 선택됩니다. 정확한 수의 행 또는 최소한 N 개의 행을 선택해야하는 경우에는이 방법이 작동하지 않습니다.
LarsH

4

이것은 오래된 질문이지만 행 수가 많은 테이블에 새 필드 (NEWID () 또는 ORDER BY rand ())를 적용하려고하면 비용이 많이 듭니다. 증분적이고 고유 한 ID가 있고 (구멍이없는 경우) GUID를 적용하거나 모든 단일 행과 유사하고 상위 X #을 가져 오는 대신 선택할 X ID ID를 계산하는 것이 더 효율적입니다.

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)

더 많은 행을 선택하려면 ID와 많은 rand () 값으로 #tempTable을 채우고 각 rand () 값을 사용하여 최소-최대 값으로 조정합니다. 그렇게하면 모든 @ randomId1 ... n 매개 변수를 정의 할 필요가 없습니다. 아래에 CTE를 사용하여 초기 테이블을 채우는 예제가 포함되어 있습니다.

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;

@Protiguous, 당신이 제안한 편집이 무작위 선택을 깨뜨 렸습니다. dbo.Tally64k 테이블에 min () 및 max ()를 적용하면 사용자가 pk id> 65556 인 행을 선택할 수 없습니다.
RIanGillis

테이블 이름 변경은 단순히 테스트 결과입니다. 올바른 테이블을 사용하는 한 실제 테이블 이름은 중요하지 않습니다. min ()과 max ()는 두 개가 아닌 하나의 쿼리로 쿼리 할 수 ​​있습니다.
인접

@Protiguous Ah, 나는 당신이 min-max를 할 때 0-65k를 사용했지만 나중에는 아니기 때문에 혼란 스럽습니다. 가장 최근의 편집 후에 실제로 성능 변경이 내 관심사 중 하나이며 어떤 등호의 측면이 실제로 중요한 영향을 줄 수 있는지와 같은 의미가없는 결정이므로 변경 사항의 성능 영향에 대해 실제로 묻고 싶었습니다. -5 개의 SET @ randomId ## 호출에도 동일한 내용이 적용됩니까? 아니면 실제 테이블에서 SELECTing이 아니기 때문에 다른가요?
RIanGillis

귀하의 질문을 이해하지 못했습니다. 1 SELECT @ id1 = rand (), @ id2 = rand (). 대신 5 SET이 왜 있는지 묻고 있습니까? 1 개의 문에서 rand ()를 여러 번 호출하면 동일한 결과가 생성되므로 SET이 분리되기 때문입니다. 나는 것 (랜드 () SQL Server에서 나는 믿는다., 결정적 기능입니다) 추측 5 세트 성능 현명한 나노초 범위에 대 1을 선택하는 것이.
인접한

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

오래된 질문이지만이 답변은 Oracle에서 실행되지 않았습니다.
Bear

SELECT * FROM (SELECT * FROM 테이블 ORDER BY DBMS_RANDOM.VALUE) WHERE rownum <number; @ 곰이 시도
Narendra

3

나는 이것이 빅 데이터에 가장 효과적이라는 것을 알았습니다.

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

TABLESAMPLE(n ROWS) or TABLESAMPLE(n PERCENT)무작위이지만 TOP n정확한 표본 크기를 얻으려면를 추가해야합니다 .

NEWID()큰 테이블에서는 사용 이 매우 느립니다.


0

이 기사 에서 설명했듯이 SQL 결과 세트를 섞으려면 데이터베이스 별 함수 호출을 사용해야합니다.

RANDOM 함수를 사용하여 큰 결과 집합을 정렬하면 속도가 매우 느릴 수 있으므로 작은 결과 집합에서는 그렇게해야합니다.

당신은 큰 결과 세트를 섞고 이후를 제한해야하는 경우, 그것은 사용하는 등 뭔가 더 나은 오라클SAMPLE(N) 또는 TABLESAMPLE에서 SQL 서버 또는 PostgreSQL을 대신 ORDER BY 절에서 임의의 기능.

따라서 다음과 같은 데이터베이스 테이블이 있다고 가정합니다.

여기에 이미지 설명을 입력하십시오

그리고 song테이블 의 다음 행 :

| 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                      |

신탁

Oracle에서는 DBMS_RANDOM.VALUE다음 예제와 같이 함수 를 사용해야합니다 .

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

위에서 언급 한 SQL 쿼리를 Oracle에서 실행하면 다음과 같은 결과 집합이 표시됩니다.

| 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      |

DBMS_RANDOM.VALUEORDER BY 절에서 사용 하는 함수 호출로 인해 노래가 무작위 순서로 나열됩니다 .

SQL 서버

SQL Server에서는 NEWID다음 예제와 같이 함수 를 사용해야합니다 .

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

위에서 언급 한 SQL 쿼리를 SQL Server에서 실행하면 다음과 같은 결과 집합이 나타납니다.

| 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) |

NEWIDORDER BY 절에서 사용 하는 함수 호출로 인해 노래가 무작위 순서로 나열됩니다 .

PostgreSQL

PostgreSQL에서는 random다음 예제와 같이 함수 를 사용해야합니다 .

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

PostgreSQL에서 위에서 언급 한 SQL 쿼리를 실행할 때 다음과 같은 결과 집합을 얻게됩니다.

| 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      |

randomORDER BY 절에서 사용 하는 함수 호출로 인해 노래가 무작위 순서로 나열됩니다 .

MySQL

MySQL에서는 RAND다음 예제와 같이 함수 를 사용해야합니다 .

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

위에서 언급 한 SQL 쿼리를 MySQL에서 실행할 때 다음과 같은 결과 집합을 얻게됩니다.

| 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            |

RANDORDER BY 절에서 사용 하는 함수 호출로 인해 노래가 무작위 순서로 나열됩니다 .


0

큰 테이블을 사용하고 있고 데이터의 10 %에 액세스하려면 다음 명령을 실행하십시오. SELECT TOP 10 PERCENT * FROM Table1 ORDER BY NEWID();

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.