2011-10-10 3 views
2

J'ai la requête suivante pour obtenir des adresses dans une distance donnée et un code postal donné. La distance est calculée en fonction des données de longitude et de latitude.Distance de calcul MySQL (solution simple)

Dans cet exemple, j'ai remplacé la saisie de l'utilisateur pour des valeurs justes (latitude = 52,64, longue = 6,88 en distance souhaitée = 10 km)

la requête:

SELECT *, 
ROUND(SQRT(POW(((69.1/1.61) * ('52.64' - latitude)), 2) + POW(((53/1.61) * ('6.88' - longitude)), 2)), 1) AS distance 
FROM lp_relations_addresses distance 
WHERE distance < 10 
ORDER BY `distance` DESC 

donne la distance de colonne inconnu Message d'erreur. en omettant l'endroit où je reçois chaque enregistrement de la table, y compris leur distance calculée. Dans ce cas, je dois aller chercher toute la table.

Comment puis-je obtenir seulement les enregistrements désirés pour aller chercher?

Merci d'avance pour tout commentaire!

Répondre

4

Vous ne pouvez pas référencer un alias dans la clause select d'une autre partie de l'instruction sql. Vous avez besoin de mettre toute l'expression dans votre clause where:

WHERE 
    ROUND(SQRT(POW(((69.1/1.61) * ('52.64' - latitude)), 2) 
     + POW(((53/1.61) * ('6.88' - longitude)), 2)), 1) < 10 

Une solution plus propre serait d'utiliser une sous-requête pour générer les données calculées:

SELECT *, distance 
    FROM (
     SELECT *, 
      ROUND(SQRT(POW(((69.1/1.61) * ('52.64' - latitude)), 2) 
       + POW(((53/1.61) * ('6.88' - longitude)), 2)), 1) AS distance 
      FROM lp_relations_addresses 
     ) d 
    WHERE d.distance < 10 
ORDER BY d.distance DESC 

Démo: http://www.sqlize.com/q96p2mCwnJ

+0

Merci encore! il est temps pour moi de dormir :) Ce problème était beaucoup trop facile à résoudre ..... – Terradon

+0

Demain, je vais essayer votre solution de nettoyage et de les comparer avec Explain, merci beaucoup encore, votre contribution m'a sauvé beaucoup d'heures pour moi! – Terradon

+2

+1 pour le site sqlize :) –

1

Vous aliasez le calcul en tant que 'distance', mais vous aliasez également la table 'lp_relations_addresses' en tant que 'distance'. Essayez de leur donner un nom différent comme ceci:

SELECT *, 
ROUND(SQRT(POW(((69.1/1.61) * ('52.64' - latitude)), 2) + POW(((53/1.61) * ('6.88' - longitude)), 2)), 1) AS distance 
FROM lp_relations_addresses addr 
WHERE distance < 10 
ORDER BY `distance` DESC 
+0

J'ai essayé aussi votre code, mais la distance dans laquelle clausule donne une distance de colonne inconnue en erreur. – Terradon

+0

Bien repéré sur la table alias clash, mais comme notes mellamokb, vous ne pouvez pas utiliser un alias dans un * où *, mais vous pouvez le faire dans un * ayant * comme le note Ilmari ... – StuartLC

2

En tant que mellamokb notes, vous ne pouvez pas référencer les alias de colonne dans la clause WHERE. You can, however, do it in a HAVING clause:

SELECT *, 
    ROUND(SQRT(POW(((69.1/1.61) * ('52.64' - latitude)), 2) + 
     POW(((53/1.61) * ('6.88' - longitude)), 2)), 1) AS distance 
FROM lp_relations_addresses 
HAVING distance < 10 
ORDER BY distance DESC 

Ps. Si vous avez beaucoup d'adresses, vous pouvez envisager d'optimiser la requête en excluant certaines d'entre elles plus tôt. Par exemple, avec des indices appropriés, la version suivante pourrait être beaucoup plus rapide:

SELECT *, 
    ROUND(SQRT(POW(((69.1/1.61) * ('52.64' - latitude)), 2) + 
     POW(((53/1.61) * ('6.88' - longitude)), 2)), 1) AS distance 
FROM lp_relations_addresses 
WHERE latitude > '52.64' - 10/(69.1/1.61) 
    AND latitude < '52.64' + 10/(69.1/1.61) 
    AND longitude > '6.88' - 10/(53/1.61) 
    AND longitude < '6.88' + 10/(53/1.61) 
HAVING distance < 10 
ORDER BY distance DESC 
+0

+1 Tho vous devez avoir la clause 'ORDER BY' * après * la clause' HAVING', alors cela fonctionne à merveille: http://www.sqlize.com/7e8TpPqiuj – mellamokb

+0

@mellamokb: Merci, corrigé. –

+0

Merci à tous pour votre contribution! m'a sauvé un peu de mal de tête – Terradon