2011-04-10 14 views
6

Diciamo che ho una lista di valori, in questo modo:MySQL: LIMIT di una percentuale della quantità di record?

id value 
---------- 
A 53 
B 23 
C 12 
D 72 
E 21 
F 16 
.. 

ho bisogno della top 10 cento di questa lista - ho provato:

SELECT id, value 
    FROM list 
ORDER BY value DESC 
    LIMIT COUNT(*)/10 

Ma questo non lo fa lavoro. Il problema è che non conosco la quantità di record prima di eseguire la query. Qualche idea?

+1

possibile duplicato del [Mysql impostare il limite di stringa] (http://stackoverflow.com/questions/1309137/mysql-set-limit-to-string) –

+1

possibile duplicato di [Converti query SQL Server in MySQL] (http://stackoverflow.com/questions/5522433/convert-sql-server-query-to- mysql) – Anax

+2

La migliore risposta dal dups: http://stackoverflow.com/questions/5522433/convert-sql-server-query-to-mysql/5522462#5522462 –

risposta

10

migliore risposta che ho trovato:

SELECT* 
FROM (
    SELECT list.*, @counter := @counter +1 AS counter 
    FROM (select @counter:=0) AS initvar, list 
    ORDER BY value DESC 
) AS X 
where counter <= (10/100 * @counter); 
ORDER BY value DESC 

Modificare il 10 per ottenere una percentuale diversa.

2

si può anche provare con quel:

SET @amount =(SELECT COUNT(*) FROM page) /10; 
PREPARE STMT FROM 'SELECT * FROM page LIMIT ?'; 
EXECUTE STMT USING @amount; 

Si tratta di MySQL bug descritto qui: http://bugs.mysql.com/bug.php?id=19795

Spero che ti aiuto.

0

Ho un'alternativa che non è stata menzionata nelle altre risposte: se si accede da qualsiasi lingua in cui si ha pieno accesso all'API MySQL (cioè non all'interfaccia CLI MySQL), è possibile avviare la query, chiedere come molte file ci saranno e poi interromperanno il ciclo se è il momento.

E.g. in Python:

... 
maxnum = cursor.execute(query) 
for num, row in enumerate(query) 
    if num > .1 * maxnum: # Here I break the loop if I got 10% of the rows. 
     break 
    do_stuff... 

Questo funziona solo con mysql_store_result(), non con mysql_use_result(), in quanto quest'ultimo richiede l'accettazione da sempre tutte le righe necessarie.

OTOH, il traffico per la mia soluzione potrebbe essere troppo alto - tutte le righe devono essere trasferite.

4

Nel caso in cui si stanno facendo questo per un fuori servizio, o una situazione casuale - ho iniziato ad usare il seguente stile:

SELECT id, value FROM list HAVING RAND() > 0.9 

Se avete bisogno di essere casuale, ma controllabile è possibile utilizzare un seme (esempio con PHP):

SELECT id, value FROM list HAVING RAND($seed) > 0.9 

Infine - se questo è un genere di cose che è necessario il pieno controllo su di voi può effettivamente aggiungere una colonna che contiene un valore casuale ogni volta che viene inserita una riga, quindi query utilizzando che

SELECT id, value FROM list HAVING `rand_column` BETWEEN 0.8 AND 0.9 

Poiché questo non richiede l'ordinamento, o ORDER BY - è O (n), piuttosto che O (n lg n)

+4

Si noti che queste query potrebbero restituire qualsiasi cosa, da nessun record a tutti (è semplicemente che la probabilità che un dato record sia nel set di risultati è 0.1). – eggyal

Problemi correlati