SQL'deki satırları rastgele seçmek nasıl?


226

MSSQL Server 2005 kullanıyorum. Benim db, "id" ve "Ad" ve yaklaşık iki sütun olan bir tablo "customerNames" var. 1.000 sonuç.

Her seferinde rastgele 5 müşteri seçmem gereken bir işlev oluşturuyorum. Birisi bana sorgu her yürütüldüğünde rastgele 5 satır (Kimlik ve Ad) alacak bir sorgu oluşturmak nasıl söyleyebilir?


Rastgele bir Veritabanı için ortak bir gereklilik değildir, bazı SQL için bir bağlantı bulmak için şaşırdım
Paxic

2
Ne kadar rasgele istediğinize bağlıdır. Bkz: msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx RAND () karşı NEW_ID karşılaştırılmasında
Shannon Kıdem

Yanıtlar:


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

Bununla birlikte, sorunuzun daha genel bir cevabı için herkes bu sayfaya geliyor gibi görünüyor:

SQL'de rastgele bir satır seçme

MySQL ile rastgele bir satır seçin:

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

PostgreSQL ile rastgele bir satır seçin:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

Microsoft SQL Server ile rastgele bir satır seçin:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

IBM DB2 ile rastgele bir satır seçin

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

Oracle ile rastgele bir kayıt seçin:

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

Sqlite ile rastgele bir satır seçin:

SELECT column FROM table 
ORDER BY RANDOM() LIMIT 1

3
Gelecekteki kullanıcılar bu soruya baktıklarında azalabilecek harici bir siteye (kabul edilen cevap gibi) bağlantı vermek yerine cevapları doğrudan SO'ya göndermek için +1.
Ray Zhou

17
Bu, her satırın rasgele bir sayı aldığı büyük tablolarda çok pahalı hale gelir ve daha sonra büyük bir dizine eklenmemiş rasgele sayı kümesi sıralanır mı?
Andrey

Bu belki de çoğu insan için açıktır, ama benim için açık değildi ... aşağıdaki sorgu her satır için yeni bir rastgele değer elde etmeyecektir: update tbl_vouchers set tbl_UsersID = (select top(1) id from tbl_Users order by NEWID()) - düzenle: Yorumlarda çalışmak için biçimlendirme alamıyorum :(
Mir

Sen Deha! Senden çok nefret ediyorum çünkü ben gidip alt sorgular ve satır numaraları ile delice uzun bir sorgu yazana kadar bunu görmedim.
greenkode

5
Uyarı: Büyük veritabanları için bu yöntemin performansı kötü olacaktır. Veritabanında milyonlarca giriş varsa, her satır için rastgele bir değer oluşturmak için gereken süreyi hayal edebiliyor musunuz? Burada daha fazla bilgi ve daha iyi bir alternatif olabilir .
Francis Ngueukam


11

Birisinin PostgreSQL çözümü istemesi durumunda:

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

Bu cevap PostgreSQL için iyidir, sınıra ihtiyacı yoktur.
aliasbody

9

Belki bu site yardımcı olacaktır.

Tıklamak istemeyenler için:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

2
en az 1'i 5 ile değiştirmeliydi :)
roman m


5

Milyonlarca satır içeren bir tablonuz varsa ve performansı önemsiyorsanız, bu daha iyi bir yanıt olabilir:

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

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


Bunun tablodaki satırların yaklaşık% 10'unu seçeceğini unutmayın. Tam sayıda satır veya en az N satır seçmeniz gerekiyorsa, bu yaklaşım çalışmaz.
LarsH

4

Bu eski bir sorudur, ancak çok sayıda satır içeren bir tabloya yeni bir alan (NEWID () veya ORDER BY rand ()) uygulamaya çalışmak, oldukça pahalıya mal olacaktır. Artımlı, benzersiz kimlikleriniz varsa (ve herhangi bir deliği yoksa), her bir satıra bir GUID veya benzeri uygulamak ve ardından en üstteki X # değerini almak yerine seçilecek kimliklerin X # değerini hesaplamak daha verimli olacaktır.

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)

Daha fazla satır seçmek isterseniz, #tempTable'ı bir ID ve bir grup rand () değeriyle doldurmak ve sonra her bir rand () değerini min-max değerlerine ölçeklemek için kullanmak isterim. Bu şekilde tüm @ randomId1 ... n parametrelerini tanımlamanız gerekmez. İlk tabloyu doldurmak için bir CTE kullanarak aşağıda bir örnek ekledim.

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;

@Sürekli, önerdiğiniz düzenleme rastgele seçimi bozdu. Dbo.Tally64k tablosuna uygulanan min () ve max () öğelerinin kullanılması, kullanıcının 65556 pk kimliğine sahip bir satır seçmesine izin vermez.
RIanGillis

Tablo adı değişikliği basitçe testten kaynaklanan bir eserdi. Doğru tablo kullanıldığı sürece gerçek tablo adı önemli değildir. min () ve max () her ikisi de yerine bir sorguda sorgulanabilir, bu da göstermeye çalıştığım şeydi.
Ocak'ta

@Protiguous Ah, görüyorum ki, kafam karıştı çünkü min-max yaparken 0-65k kullandınız, ancak daha sonra değil. En son düzenlemenizden sonra, aslında yaptığınız değişikliklerin performans sonuçları hakkında soru sormak istedim, çünkü performans ayarı ilgi alanımdan biri ve eşit derecede hangi tarafın bir şey yerleştirdiğinizi belirtmek gibi görünüşte anlamsız kararlar gerçekten önemli bir etkiye sahip olabilir - - Aynı şey 5 SET @ randomId ## çağrıları için de geçerli miydi? Yoksa gerçek bir tablodan SEÇMEDİĞİNDEN farklı mı?
RIanGillis

Sorunu anladığımdan emin değilim. Neden sadece 1 SELECT @ id1 = rand (), @ id2 = rand () .. yerine 5 SET olduğunu soruyor musunuz? Çünkü 1 deyimdeki bir rand () işlevine yapılan birden çok çağrı aynı sonucu, dolayısıyla ayrılmış SET'i üretecektir. (Rand () SQL Server üzerinde deterministik bir işlevdir, inanıyorum.) 1 select vs 5 set nanosaniye aralığında performans tahmin olduğunu tahmin ediyorum .
Protiguous

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

Eski soru, ama bu cevap benim için Oracle'da çalışmadı.
Ayı

SELECT * FROM (SELECT * tablodan ORDER BY DBMS_RANDOM.VALUE) Nerede rownum <sayı; @Bear try this
Narendra

3

Bunu büyük veriler için en iyi sonucu buldum.

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

TABLESAMPLE(n ROWS) or TABLESAMPLE(n PERCENT)rastgele ancak TOP ndoğru örnek boyutunu almak için eklemeniz gerekir .

Kullanılması NEWID()büyük tablolarda çok yavaştır.


0

Bu makalede açıkladığım gibi , SQL sonuç kümesini karıştırmak için veritabanına özgü bir işlev çağrısı kullanmanız gerekir.

RANDOM işlevini kullanarak büyük bir sonuç kümesini sıralamanın çok yavaş olabileceğini unutmayın, bu nedenle bunu küçük sonuç kümelerinde yaptığınızdan emin olun.

Büyük bir sonuç kümesi karıştırmak ve daha sonra bunu sınırlamak varsa, o zaman kullanım gibi bir şey daha iyidir OracleSAMPLE(N) veya TABLESAMPLEiçinde SQL Server veya PostgreSQL yerine ORDER BY yan tümcesinde rastgele fonksiyonu.

Yani, aşağıdaki veritabanı tablosuna sahip olduğumuzu varsayarsak:

resim açıklamasını buraya girin

Ve songtabloda aşağıdaki satırlar :

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

torpil

Oracle'da, DBMS_RANDOM.VALUEaşağıdaki örnekte gösterildiği gibi işlevi kullanmanız gerekir :

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

Oracle'da yukarıda belirtilen SQL sorgusunu çalıştırırken, aşağıdaki sonuç kümesini alacağız:

| 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 deyimi tarafından kullanılan işlev çağrısı sayesinde şarkıların rasgele sırada listelendiğine dikkat edin .

SQL Server

SQL Server'da, NEWIDaşağıdaki örnekte gösterildiği gibi işlevi kullanmanız gerekir :

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

Yukarıda belirtilen SQL sorgusu SQL Server'da çalıştırıldığında, aşağıdaki sonuç kümesini alacağız:

| 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 deyimi tarafından kullanılan işlev çağrısı sayesinde şarkıların rasgele sırada listelendiğine dikkat edin .

PostgreSQL

PostgreSQL'de, randomaşağıdaki örnekte gösterildiği gibi işlevi kullanmanız gerekir :

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

PostgreSQL'de yukarıda belirtilen SQL sorgusunu çalıştırırken, aşağıdaki sonuç kümesini alacağız:

| 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 deyimi tarafından kullanılan işlev çağrısı sayesinde şarkıların rasgele sırada listelendiğine dikkat edin .

MySQL

MySQL'de, RANDaşağıdaki örnekte gösterildiği gibi işlevi kullanmanız gerekir :

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

MySQL'de yukarıda belirtilen SQL sorgusunu çalıştırırken, aşağıdaki sonuç kümesini alacağız:

| 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 deyimi tarafından kullanılan işlev çağrısı sayesinde şarkıların rasgele sırada listelendiğine dikkat edin .


0

Büyük tablo kullanıyorsanız ve verilerin yüzde 10'una erişmek istiyorsanız, aşağıdaki komutu çalıştırın: SELECT TOP 10 PERCENT * FROM Table1 ORDER BY NEWID();

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.