2017-09-07 5 views
1

J'ai un site et permet aux utilisateurs de rechercher d'autres utilisateurs dans un rayon spécifié de leur propre code postal. Je dois d'abord localiser la latitude et la longitude de l'utilisateur et utiliser ces données pour calculer et trouver d'autres utilisateurs. J'ai préparé la requête suivante basée sur les 2 tables requises mais j'obtiens des erreurs qu'un autre alias est nécessaire. Si je code dur les valeurs alors des parties du travail de requête trouvent quand je les sépare, mais avec plusieurs jointures et sous-requêtes j'ai échoué. Vous cherchez des conseils ou de l'aide. Les structures de requête et de table sont incluses ci-dessous.Localisation des utilisateurs dans un rayon d'un autre code postal

Requête modifiée et jeu de données basé sur le retour d'informations. Je ne reçois plus d'erreurs mais je ne reçois aucune donnée retournée pour la requête.

Déclaration SQL

SELECT u.username, u.zip, m.longitude, 
    m.latitude, 
    m.zip from users u, zipcodes m 
LEFT JOIN (SELECT s.zip, 
    s.username from users s) t 
on m.zip = t.zip 
    and t.username = 'tester55' 
    INNER join (SELECT zip, city, state, (3959 * acos(cos(radians(@m.latitude)) * cos(radians(latitude)) 
    * cos(radians(longitude) - radians(@m.longitude)) + sin(radians(@m.latitude)) * sin(radians(latitude)))) AS distance 
FROM zipcodes 
HAVING distance < 5000 
ORDER BY distance) as RelevantCodes 
    ON (t.zip=RelevantCodes.zip) 

utilisateur Tableau

username  zip 
----------------------- 
    tester55  60608 
    Tester1  60608 
    iosuser1  73120 
    Tester3  60608 

Code postal Tableau

latitude  longitude  zip 
-------------------------------- 
41.8515  -87.6694  60608 
35.5835  -97.5638  73120 
36.3169  -94.1545  72758 
+0

En ce qui concerne votre édition: Peut-être que vous êtes penser trop compliqué. Par exemple, vous pouvez remplacer 'LEFT JOIN (SELECT s.zip, s.username des utilisateurs s) t' par' LEFT JOIN users' (et remplacer 't' par' users' dans le reste du code, bien sûr) . Mais depuis que j'ai donné une solution de travail, je ne vais pas analyser votre nouveau complètement :-) – Binarus

Répondre

1

Je n'ai pas le temps en ce moment pour élaborer une requête correcte, mais Je vais montrer ce qui ne va pas avec la requête existante à première vue.

1) En ce qui concerne votre question actuelle: Le message d'erreur indique ERROR 1248 (42000): Every derived table must have its own alias et indique déjà ce qui ne va pas. La sous-requête dans la partie suivante

LEFT JOIN (select s.zip, 
    s.username, 
    m.longitude, 
    m.latitude, 
    m.zip 
from users s) on u.zip = s.zip 

a besoin de son propre alias, ce qui devrait éventuellement

LEFT JOIN (select s.zip, 
    s.username, 
    m.longitude, 
    m.latitude, 
    m.zip 
from users s) t on u.zip = t.zip 

(notez le T après la parenthèse fermante et le remplacement de s.zip par t.zip) . Mais même si vous faites cela, vous rencontrerez le problème 2 (voir la section suivante).

2) La sous-requête

(select s.zip, 
     s.username, 
     m.longitude, 
     m.latitude, 
     m.zip 
     from users s) 

jetteront une autre erreur car la table m ne sait pas dans ce sous-requête.

Si vous parvenez à le résoudre correctement, je vous suggère de modifier votre question et de nous en faire part. Si ce n'est pas le cas, postez un commentaire ou modifiez votre question en décrivant les autres problèmes que vous rencontrez.

EDIT

J'ai maintenant élaboré une solution pour vous:

SELECT zipcodes.zip, 
     (3959 * acos(cos(radians(zipcodes.latitude)) * 
        cos(radians(center.latitude)) * 
        cos(radians(zipcodes.longitude) - 
         radians(center.longitude)) + 
        sin(radians(zipcodes.latitude)) * 
        sin(radians(center.latitude)))) AS distance FROM 
    (SELECT users.username, 
      users.zip, 
      zipcodes.latitude, 
      zipcodes.longitude FROM 
    (users JOIN zipcodes ON users.zip = zipcodes.zip) 
    WHERE (username='Tester1') 
) center, zipcodes 
HAVING (distance < 5000) 
ORDER BY distance; 

Ce sélectionne tous les codes postaux qui sont à la distance désirée, classés par ordre de distance.

Comme vous pouvez le remarquer, j'ai simplifié le code. S'il vous plaît noter également que j'ai testé cela en fonction de vos anciennes données (les données que vous avez montré avant votre modification), mais en utilisant Tester1 au lieu de tester55.

Vous avez en effet besoin de HAVING au lieu de WHERE lors du filtrage, donc ma déclaration initiale à ce sujet était trompeuse.La raison en est que MySQL n'autorise pas les colonnes calculées (dans ce cas: distance) dans les clauses WHERE, mais dans les clauses HAVING. C'est un comportement non-standard; Habituellement, vous devez résoudre ce problème d'une autre manière. Je ne vais pas m'étendre là-dessus parce que c'est une autre question potentiellement inquiétante qui n'est pas étroitement liée à votre question initiale.

EDIT 2

Enfin, voici la version qui donne le nom d'utilisateur en plus:

SELECT zipcodes.zip, 
     users.username, 
     (3959 * acos(cos(radians(zipcodes.latitude)) * 
        cos(radians(center.latitude)) * 
        cos(radians(zipcodes.longitude) - 
         radians(center.longitude)) + 
        sin(radians(zipcodes.latitude)) * 
        sin(radians(center.latitude)))) AS distance FROM 
    ((SELECT users.username, 
      users.zip, 
      zipcodes.latitude, 
      zipcodes.longitude FROM 
     (users JOIN zipcodes ON users.zip = zipcodes.zip) 
     WHERE (username='Tester1') 
    ) center, zipcodes) INNER JOIN users ON zipcodes.zip = users.zip 
WHERE (users.username <> 'Tester1') 
HAVING (distance < 5000) 
ORDER BY distance; 

S'il vous plaît noter que vous devez le troisième de la dernière ligne pour filtrer l'utilisateur que vous calculez les distances pour. Si vous ne faites pas cela, le résultat inclura une ligne avec l'utilisateur lui-même (dans ce cas: Tester1) et une distance de (presque) 0.

EDIT 3

Ce qui suit est une version telle que demandée par les commentaires ci-dessous (rayon recherche souhaité stocké sous forme de champ seekingdistance supplémentaire dans le tableau users):

SELECT zipcodes.zip, 
     users.username, 
     center.seekingdistance, 
     (3959 * acos(cos(radians(zipcodes.latitude)) * 
        cos(radians(center.latitude)) * 
        cos(radians(zipcodes.longitude) - 
         radians(center.longitude)) + 
        sin(radians(zipcodes.latitude)) * 
        sin(radians(center.latitude)))) AS distance FROM 
    ((SELECT users.username, 
      users.zip, 
      users.seekingdistance, 
      zipcodes.latitude, 
      zipcodes.longitude FROM 
     (users JOIN zipcodes ON users.zip = zipcodes.zip) 
     WHERE (username='Tester1') 
    ) center, zipcodes) INNER JOIN users ON zipcodes.zip = users.zip 
WHERE (users.username <> 'Tester1') 
HAVING (distance < center.seekingdistance) 
ORDER BY distance; 
+0

merci de votre aide. Votre retour m'a aidé à surmonter l'erreur initiale maintenant que j'ai affaire à des erreurs indiquant des colonnes zip en double. J'utilise vos conseils restants pour essayer de trouver une solution, mais je suis honnêtement perplexe. – techgirl

+0

Je finirai par essayer de trouver une bonne réponse, mais veuillez éditer votre question et fournir des données correctes. La requête que vous avez montrée jusqu'ici ne montrera aucun résultat puisque le fichier zip de '' test55'' ne se trouve pas dans la table 'zipcodes'. Bien que cela ne nous empêche pas d'élaborer une requête syntaxiquement correcte, cela nous empêchera de vérifier si cette requête donne des résultats significatifs. – Binarus

+0

Merci. J'ai révisé la requête et suis maintenant sans erreur, mais elle ne renvoie aucune donnée. J'ai mis à jour la question avec la requête révisée et corrige les données avec l'ensemble d'échantillons. – techgirl