IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Sous requete IN avec plus d'un champs


Sujet :

Langage SQL

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 19
    Points : 17
    Points
    17
    Par défaut Sous requete IN avec plus d'un champs
    bonjour à tous,
    j'ai 3 tables:
    une table stages avec un champs id_lieu
    une table lieux avec un champs id et un champs cp (code postal)
    une table villes avec un champs c_p (code postal) et deux champs lat et lon (latitude et longitude)

    si je veux afficher les stages ayant lieu dans le 92220:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM stages WHERE id_lieu IN (SELECT id FROM lieux WHERE cp = '92220')
    jusqu'ici tout va bien.
    J'utilise cette requête pour connaitre les 10 villes les plus proches:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT c_p,(6366*acos(cos(radians(".$LAT."))*cos(radians(`ep_villes`.`lat`))*cos(radians(`villes`.`lon`)-radians(".$LONG."))+sin(radians($LAT))*sin(radians(`villes`.`lat`)))) 
    AS Proximite FROM villes 
    ORDER BY Proximite LIMIT 1,10
    Vous me voyez venir, comment afficher non pas les stages ayant lieu dans les 10 villes les plus proches, mais plutôt, les 10 stages les plus proches!

    ce qui serait la requête suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT * FROM stages WHERE id_lieu IN (SELECT id FROM lieux WHERE cp IN
    (
    SELECT c_p,(6366*acos(cos(radians(".$LAT."))*cos(radians(`ep_villes`.`lat`))*cos(radians(`villes`.`lon`)-radians(".$LONG."))+sin(radians($LAT))*sin(radians(`villes`.`lat`)))) AS Proximite FROM villes ORDER BY Proximite LIMIT 1,10
    )
    )
    qui bien sûr ne fonctionne pas pour au moins 3 raisons (plusieurs champs dans le select, le order et le limit)

    Toute aide sera la bienvenue
    Merci d'avance

  2. #2
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Bonjour,


    Mettez-vous aux jointures et votre problème sera résolu assez rapidement je pense.
    http://sqlpro.developpez.com/cours/sqlaz/jointures/

    Dans le cas où un stage peut être dans plusieurs lieux différent le problème sera un peu plus corsé, et là il faudra connaitre votre sgbd pour trouver une solution appropriée.

  3. #3
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    La structure de ta BDD me semble bancale !
    Sais-tu qu'une ville peut avoir plusieurs codes postaux et qu'un code postal peut concerner plusieurs villes ?
    En plus, un code postal n'est pas une bonne clé.
    À moins que ta table des villes soit en fait une table des codes postaux et que les coordonnées géographiques soient celles du barycentre du secteur couvert par le code postal ?

    Connais-tu les jointures ?
    Ta première requête peut s'écrire ainsi, en évitant la guerre des étoiles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT les_colonnes_necessaires_et_pas_etoile
    FROM stages s
    INNER JOIN lieux l ON l.id = s.id_lieu
    WHERE l.cp = '92220'
    Ta deuxième requête me semble comporter une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT c_p,(6366*acos(cos(radians(".$LAT.")) 
        * cos(radians(`ep_villes`.`lat`)) 
        * cos(radians(`villes`.`lon`) 
        - radians(".$LONG.")) 
        + sin(radians($LAT)) 
        * sin(radians(`villes`.`lat`)))) 
    AS Proximite 
    FROM villes 
    ORDER BY Proximite 
    LIMIT 1,10
    Dans la formule, tu utilises la colonne 'lat' de la table 'ep_villes' et cette table ne figure pas dans la partie FROM de ta requête !

    Vous me voyez venir, comment afficher non pas les stages ayant lieu dans les 10 villes les plus proches, mais plutôt, les 10 stages les plus proches!
    On peut avoir le résultat de SHOW CREATE TABLE sur chaque table ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 19
    Points : 17
    Points
    17
    Par défaut
    En fait je n'utilise pas le code postal mais le code insee des communes.

    merci pour la première requête modifiée.

    pour la seconde elle fonctionne, j'ai fait une erreur de copie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT c_p,(6366*acos(cos(radians(".$LAT.")) 
        * cos(radians(`villes`.`lat`)) 
        * cos(radians(`villes`.`lon`) 
        - radians(".$LONG.")) 
        + sin(radians($LAT)) 
        * sin(radians(`villes`.`lat`)))) 
    AS Proximite 
    FROM villes 
    ORDER BY Proximite 
    LIMIT 1,10

  5. #5
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    En fait je n'utilise pas le code postal mais le code insee des communes.
    OK je préfère !
    Même si ça reste une mauvaise clé !

    Dans quelles villes se situent les stages ?
    Comme tu n'as toujours pas donné la structure complète des tables, je suis obligé d'imaginer un peu !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT s.id AS id_stage,
        v.cp AS code_ville,
        v.lat AS latitude, 
        v.lon AS longitude
    FROM stage s 
    INNER JOIN lieux l ON l.id = s.id_lieu
        INNER JOIN ville v ON v.cp = l.cp
    Si tu bidouille ça avec ta requête pour trouver les 10 villes les plus proches, tu devrais trouver les 10 stages les plus proches.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 19
    Points : 17
    Points
    17
    Par défaut
    Merci CinePhil,
    tu as bien compris la structure de mes table et j'ai bien compris la requête que tu me propose, c'est parfait.
    Par contre je parviens pas à bidouiller pour intégrer ma requête de calcul de distance. Si tu peux me donner une piste, j'ai le cerveau qui fume là...

    Merci à toi

  7. #7
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Quel est ton besoin exactement ?
    À partir de coordonnées géographiques, connaître les 10 stages les plus proches ?
    Si les variables $LAT et $LONG sont les coordonnées de l'endroit considéré, il te suffit je pense de faire cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT c_p,(6366 * acos(cos(radians(".$LAT.")) 
        * cos(radians(`villes`.`lat`)) 
        * cos(radians(`villes`.`lon`) 
        - radians(".$LONG.")) 
        + sin(radians($LAT)) 
        * sin(radians(`villes`.`lat`)))) 
    AS Proximite 
    FROM villes v
    INNER JOIN lieux l ON l.cp = v.cp
      INNER JOIN stage s ON s.id_lieu = l.id
    ORDER BY Proximite 
    LIMIT 1,10
    Par rapport à ta requête, le fait de faire la jointure interne vers les stages ne retiendra que les villes où se déroulent des stages.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 19
    Points : 17
    Points
    17
    Par défaut parfait
    j'ai modifié toutes mes requêtes en utilisant les jointures, et cela marche parfaitement. On voit en effet les choses 'différemment' en utilisant cette technique.
    Merci encore à toi, et bon week end!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2002] requete ajout avec meme nom de champ
    Par poliart dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 09/07/2009, 12h07
  2. [MySQL] Requete Select avec choix dynamique des champs de condition
    Par belaggoun2000 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 08/02/2009, 11h30
  3. [MySQL] requete update avec fonction php sur champs
    Par SpaceFrog dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 21/10/2008, 09h14
  4. Table access avec plus de 200 champs
    Par sakia dans le forum Modélisation
    Réponses: 15
    Dernier message: 22/08/2007, 23h37
  5. requete sql avec between sur des champs de type Date
    Par ersoufiane dans le forum Langage SQL
    Réponses: 2
    Dernier message: 02/08/2006, 19h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo