sql >> Databasteknik >  >> RDS >> Mysql

Hur väljer man snabbt 3 slumpmässiga poster från en 30k MySQL-tabell med ett where-filter med en enda fråga?

Ful, men snabb och slumpmässig. Kan bli väldigt fult väldigt snabbt, speciellt med justering som beskrivs nedan, så se till att du verkligen vill ha det så här.

(SELECT Products.ID, Products.Name
FROM Products
    INNER JOIN (SELECT RAND()*(SELECT MAX(ID) FROM Products) AS ID) AS t ON Products.ID >= t.ID
WHERE Products.HasImages=1
ORDER BY Products.ID
LIMIT 1)

UNION ALL

(SELECT Products.ID, Products.Name
FROM Products
    INNER JOIN (SELECT RAND()*(SELECT MAX(ID) FROM Products) AS ID) AS t ON Products.ID >= t.ID
WHERE Products.HasImages=1
ORDER BY Products.ID
LIMIT 1)

UNION ALL

(SELECT Products.ID, Products.Name
FROM Products
    INNER JOIN (SELECT RAND()*(SELECT MAX(ID) FROM Products) AS ID) AS t ON Products.ID >= t.ID
WHERE Products.HasImages=1
ORDER BY Products.ID
LIMIT 1)

Första raden visas oftare än den borde

Om du har stora luckor mellan ID:n i din tabell, kommer rader direkt efter sådana luckor att ha större chans att hämtas av den här frågan. I vissa fall kommer de att dyka upp betydligt oftare än de borde. Detta kan inte lösas generellt, men det finns en fix för ett vanligt särskilt fall:när det finns ett gap mellan 0 och det första befintliga ID:t i en tabell.

Istället för underfrågan (SELECT RAND()*<max_id> AS ID) använd något som (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)

Ta bort dubbletter

Frågan, om den används som den är, kan returnera dubbletter av rader. Det är möjligt att undvika det genom att använda UNION istället för UNION ALL . På detta sätt kommer dubbletter att slås samman, men frågan garanterar inte längre att den returnerar exakt 3 rader. Du kan också komma runt det genom att hämta fler rader än du behöver och begränsa det yttre resultatet så här:

(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3

Det finns fortfarande ingen garanti för att 3 rader kommer att hämtas. Det gör det bara mer sannolikt.



  1. Generera CREATE-satser för alla MySql-tabeller

  2. Utforska SQL Server 2016 Query Store GUI

  3. Hur man ersätter en Intermediate MySQL eller MariaDB Master med en Binlog Server med MaxScale

  4. Kopiera en MySQL-tabell inklusive index