2009-10-28 13 views
10

Questo è probabilmente più semplice di quanto lo sto facendo, ma in pratica quello che devo fare è selezionare la riga che ha il numero più vicino in una colonna come valore specificato. Per esempio:Seleziona il valore numerico più vicino con query MySQL

elenco di valori in banca dati per 3 righe di una colonna specificata: 10, 15, 16

Se specifico che voglio la riga che è più vicino a 14, sarebbe scegliere la riga con 15

Inoltre, se ci sono più di 2 file della stessa distanza, sceglierne uno a caso.

risposta

21

Una possibilità sarebbe qualcosa sulla falsariga di:

select the_value, 
     abs(the_value - 14) as distance_from_test 
from  the_table 
order by distance_from_test 
limit 1 

Per selezionare un record a caso, è possibile aggiungere , rand() alla clausola order by. Lo svantaggio di questo metodo è che non si ottiene alcun beneficio dagli indici perché è necessario ordinare il valore derivato distance_from_test.

Se si dispone di un indice su the_value e si riduce il requisito che il risultato sia casuale nel caso di vincoli, è possibile eseguire una coppia di query a intervallo limitato per selezionare il primo valore immediatamente sopra il valore di test e il primo valore immediatamente al di sotto del valore di test per scegliere la più vicina al valore di test:

(
select the_value 
from  the_table 
where the_value >= 14 
order by the_value asc 
limit 1 
) 
union 
(
select the_value 
from  the_table 
where the_value < 14 
order by the_value desc 
limit 1 
) 
order by abs(the_value - 14) 
limit 1 
+0

Pedantic: 'ASC' è il tipo/ordine predefinito - non c'è bisogno di specificarlo. –

+2

Generalmente lo inserisco nelle domande che scrivo, affinché non torni più tardi e pensi di aver dimenticato di inserire un ordinamento in :-). –

3

per utilizzare un indice, è possibile selezionare il valore minimo sopra il bersaglio, e il valore massimo di seguito. Quindi hai solo due valori da controllare.

2

Come gestiresti i tie breaker? Perché questo sarà solo prendere la prima:

SELECT t.col 
    FROM TABLE t 
ORDER BY ABS(t.col - @val) 
    LIMIT 1 

Indice alternativa sicura:

SELECT xt.col 
    FROM (SELECT t.col, 
       ABS(t.col - @val) 'diff' 
      FROM TABLE t) xt 
ORDER BY xt.diff 
    LIMIT 1 
Problemi correlati