10
votes

Comment obtenir la valeur la plus proche de la base de données dans MySQL

J'utilise mysql et codeigniter . J'ai des numéros de points flottants dans ma base de données tels que

  • 8.3456
  • 8.5555
  • 4.5556

    je veux ... xxx

    mais je ne peux pas utiliser valeur = $ myvalue dans ma requête SELECT parce que $ myvalue n'est pas exactement égal aux valeurs de la base de données. J'ai besoin d'obtenir la valeur la plus proche sur $ myvalue à partir de la base de données.

    si $ myvalue est 5 Je veux sélectionner la valeur 4.5556 .

    Comment puis-je faire cela dans mysql? < / p>


1 commentaires

Si vous avez quelques lignes, les réponses vers le haut seront suffisantes - Toutefois, si vous avez des millions de lignes, je ne les recommanderais pas, car ils numériseront toute la table - voir ma réponse au bas (le compromis étant lisibilité comme La requête est beaucoup plus longue - mais beaucoup plus rapide aussi)


11 Réponses :


2
votes

Prenez la première valeur à partir des éléments suivants:

select * from table order by abs(value - $myvalue);


0 commentaires

0
votes
SELECT * FROM table1 ORDER BY ABS(value - '$myvalue') LIMIT 1 

0 commentaires

15
votes

En supposant que vous avez une tolérance de 10% (+/-), vous pouvez essayer quelque chose comme:

select * from table 
where value >= ($myvalue * .9) and value <= ($myvalue * 1.1) 
order by abs(value - $myvalue) limit 1


4 commentaires

Et si la myvalue de $ la plus proche est plus que votre% arbitraire de toute valeur?


L'exigence initiale n'est pas très claire. Bien sûr, s'il n'y a pas de "portée acceptée", vous pouvez dire que 10000000000 est suffisamment proche de "1", en supposant qu'il n'y ait rien de mieux dans votre DB. Dans ce cas, vous pouvez laisser tomber la partie "où".


Notez que cela échouera si $ myvalue est 0. Si vous voulez vraiment faire cela, vous devez ajouter ou (($ molvalue> = (valeur * .9)) et myvalue <= (valeur * 1.1)))


Cela ne montrera pas la valeur la plus proche s'il mettra 6 par exemple -> Cependant, vous étiez sur la bonne voie avec le> = et ABS sur Taille entière!) -> Quelqu'un cherche qui voit ceci s'il vous plaît voir mon fond de réponse qui donnera un résultat rapide et correct.



-1
votes

Lire cette page http: //dev.mysql .com / doc / Refman / 5.1 / fr / mathématique-fonctions.html # Fonction_round

Mais votre sélection ressemblerait à ce p>

select value from table where ROUND(value) = $myvalue 


4 commentaires

Et si le $ myvalue est-il supérieur à 1 de toute valeur?


@Bohemian - à un moment donné, vous allez avoir besoin d'un point de coupure pour correspondre à la valeur


@Bohemian, non, vous ne dépendez pas entièrement de votre application, et si vous avez besoin d'une coupure, elle doit toujours être un pourcentage des valeurs d'origine. Et si vous ne traitez pas avec 8.12 , mais avec 15 481 254,454 875 544 4545.1 ?


La question est claire: "Choisissez la la plus proche valeur". Cela ne dit rien de à quelle distance la valeur est ... pourrait être de 1000. Votre réponse est tout simplement "fausse".



20
votes
select * 
from table 
order by abs(value - $myvalue)
limit 1

1 commentaires

Fait probablement une balayage de table (lente).



0
votes

Malheureusement, je pense que votre base de données fera probablement une analyse de la table complète des solutions impliquant ABS , afin qu'ils soient (très) lent une fois que votre table se développe. Une solution rapide peut être trouvée dans ce Thread antérieur .


0 commentaires

0
votes
SELECT number, ABS( number - 2500 ) AS distance
FROM numbers
ORDER BY distance
LIMIT 6
Selecting closest values in MySQL

0 commentaires

11
votes
(
select   *
from     table
where    value >= $myvalue
order by value asc
limit 1
)
union
(
select   *
from     table
where    value < $myvalue
order by value desc
limit 1
)
order by abs(value - $myvalue)
limit 1
This may look counter-intuitive but the speed will be greater than the other queries shown so far.This is due to the fact that a greater than and less than query is quicker.Then doing an ABS on two values is nothing.This will give you the quickest return in a single query I can think of.Doing an ABS on a whole table will be slow as it will scan the whole table.

0 commentaires

0
votes

Essayez ceci:

SELECT *,abs((columnname -Yourvalue)) as near
  FROM table
 WHERE order by near limit 0,1


0 commentaires

3
votes

Obtenez la plus grande valeur similaire à $ VAL:

SELECT * FROM tab ORDER BY abs(val - $val) LIMIT 1


0 commentaires

2
votes

Dans mon cas, j'utilisais les géolocations des navigateurs et j'essayais de trouver une ville / un état le plus proche basé sur les coordonnées que j'avais dans une table.

Structure de table: p>

$city = Zipcodes::selectRaw
    ('city_state, zipcode,  ( ABS( lat - ? ) + ABS( lon - ?) ) AS distance', [$lat, $lon])
        ->orderBy('distance')
        ->first();

echo $city->city_state


0 commentaires