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 :

Problème de requête sql


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mai 2008
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 17
    Par défaut Problème de requête sql
    Bonjour à tous,
    Ce n'est pas la première fois que je fais appelle à vos lumières et je suis certain que je ne serai pas déçu.
    J'ai une requête un peu complexe à faire en sql et je bloque. Voici ce que j'ai déjà produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT A.id 
    FROM sujets A, derniereVisite B 
    WHERE B.id_mec = 1 
      AND A.id_gpe = 144 
      AND A.id = B.id_sujet 
      AND B.quand < A.last_msg 
    ORDER BY A.last_msg ASC
    Cette requête me permet de sortir tous les sujets du groupe 144 qui contiennent des messages que le visiteur 1 n'a pas lus.

    La table sujets a une colonne "id", une colonne "id_gpe" qui indique dans quel groupe il est, une colonne "last_msg" qui indique la date du dernier message posté.
    La table derniereVisite a une colonne "id_mec" qui indique l'id de l'utilisateur, une colonne "id_sujet" qui indique l'id du sujet, une colonne "quand" qui indique la date de dernière visite de l'utilisateur dans le sujet.

    J'aimerai rajouter dans ma requête les sujets que l'utilisateur n'a JAMAIS visités. Est-ce que quelqu'un a une idée? Je sèche là...

    Merci pour l'aide que vous pourrez m'apporter.

  2. #2
    Membre Expert
    Avatar de Hephaistos007
    Profil pro
    Enseignant Chercheur
    Inscrit en
    Décembre 2004
    Messages
    2 493
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 493
    Par défaut
    A : Sélectionne la liste de tous les sujets.
    B : Sélectionne la liste des sujets que l'utilisateur a visité.

    Par conséquent, A - B te donne les sujets que l'utilisateur n'a PAS visité.

    Il faut donc utiliser l'opérateur de soustraction en SQL. Attention, il n'existe pas sous MySQL par exemple.
    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  3. #3
    Membre averti
    Inscrit en
    Mai 2008
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 17
    Par défaut
    Ca paraît simple quand tu le dis!! :-)

    Et du coup j'utilise mysql avec php. Je commence à m'intéresser à PDO, est-ce que ça pourrait être une alternative et donc m'autoriser la soustraction?

  4. #4
    Membre Expert
    Avatar de Hephaistos007
    Profil pro
    Enseignant Chercheur
    Inscrit en
    Décembre 2004
    Messages
    2 493
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 493
    Par défaut
    Citation Envoyé par aouchachacha Voir le message
    Ca paraît simple quand tu le dis!! :-)

    Et du coup j'utilise mysql avec php. Je commence à m'intéresser à PDO, est-ce que ça pourrait être une alternative et donc m'autoriser la soustraction?
    Non, PDO n'a rien à voir dans ce problème (mais c'est une bonne chose de l'utiliser). Si tu souhaites vraiment conserver le SGBD MySQL, tu peux reformuler la soustraction ainsi :

    "Sélectionner la liste des sujets QUI N'EXISTENT PAS dans la liste des sujets que l'utilisateur a visité". Mais j'ai également un doute sur l'existence de la clause NOT EXIST sous MySQL

    Au pire, il existe une troisième technique basé sur une jointure externe sur laquelle on repérer des valeurs nulles (Cf. http://www.developpez.net/forums/d15...e-minus-mysql/)
    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  5. #5
    Membre averti
    Inscrit en
    Mai 2008
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 17
    Par défaut
    Merci je vais regarder ça. En attendant j'avais testé un truc comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT A.id, B.id_gpe, C.quand 
    FROM `sujets` A, `adhesion` B, `derniereVisite` C
    WHERE B.id_mbr = 1
    AND B.etat = 1
    AND A.id_gpe = B.id_gpe
    AND A.id = IF(EXISTS(C.id_mec = 1 AND C.id_sujet = A.id),C.id_sujet,A.id)
    ORDER BY `quand` ASC
    Ca ne marche pas mais je viens seulement de découvrir la clause EXISTS donc ma syntaxe est surement mauvaise

    PS: je précise que j'ai rajouté une table 'adhesion' dans laquelle je retourne tous les groupes auxquels l'utilisateur adhère.

  6. #6
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    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 818
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par Hephaistos007 Voir le message
    "Sélectionner la liste des sujets QUI N'EXISTENT PAS dans la liste des sujets que l'utilisateur a visité". Mais j'ai également un doute sur l'existence de la clause NOT EXIST sous MySQL
    C'est NOT EXISTS et ça existe chez MySQL.

    Au pire, il existe une troisième technique basé sur une jointure externe sur laquelle on repérer des valeurs nulles (Cf. http://www.developpez.net/forums/d15...e-minus-mysql/)
    En principe, dans ce cas, le NOT EXISTS est plus performant que la jointure externe mais avec MySQL on ne sait jamais.

    On peut avoir la définition des tables, un petit jeu de données et le résultat attendu car je ne suis pas bien sûr de comprendre la totalité du besoin exprimé dans le premier message ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    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 !

  7. #7
    Membre averti
    Inscrit en
    Mai 2008
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 17
    Par défaut
    J'ai trois tables :
    - une indiquant les groupes auxquels les utilisateurs adhèrent, construite comme ça

    TABLE adhesion
    |id|id_gpe|id_mbr|etat|
    |0 | 144 | 1 | 1 |
    - une contenant les sujets

    TABLE sujets
    |id|id_gpe|last_msg|
    |11| 144 | 1230000001|
    |12| 144 | 1230000005|
    |13| 144 | 1230000010|
    - une indiquant la date de derniere visite de l'utilisateur dans chaque sujet

    TABLE derniereVisite
    |id|id_mec|id_sujet|quand|
    |0 | 1 | 11 |1230000005|
    |1 | 1 | 12 |1230000002|
    Et je cherche à connaître les sujets qui contiennent des messages postés après la dernière visite.

    Donc là on aurait le sujet 12 car la dernière visite est supérieure et le 13 car il n'a jamais visité ce sujet (absence de résultat pour ce sujet et cet utilisateur dans la table derniereVisite)

    J'espère que ça sera plus clair, merci!

  8. #8
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    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 818
    Billets dans le blog
    14
    Par défaut
    Essaie 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
    13
    14
    15
    16
    SELECT tmp.id
    FROM
    (
        SELECT a.id_mbr, s.id AS id_sujet, s.last_msg
        FROM sujet s
        INNER JOIN adhesion a ON a.id_gpe = s.id_gpe
        LEFT OUTER JOIN
        WHERE a.idmbr = 1
            AND a.etat = 1
            AND a.id_gpe = 144
    ) tmp 
    LEFT OUTER JOIN derniereVisite d 
        ON d.id_mec = tmp.id_mbr
        AND d.id_sujet = tmp.id_sujet
    WHERE tmp.last_msg > d.quand
        OR d.id IS NULL
    La sous-requête doit donner tous les sujets du groupe 144 pour l'utilisateur 1 à l'état 1 puis on restreint cet ensemble aux sujets dont le dernier message est postérieur à la dernière visite de l'utilisateur ou à ceux qui n'ont jamais été visité.
    Ça répond à ton besoin ?

    Comme il y a deux conditions, il vaut mieux cette fois la jointure externe.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    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 !

  9. #9
    Membre averti
    Inscrit en
    Mai 2008
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 17
    Par défaut
    MySQL a répondu:
    #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE a.id_mbr = 1
    AND a.etat = 1
    AND a.id_gpe = 144
    ) tmp
    LEFT' at line 8
    J'ai peut-être oublié de préciser que j'étais sous MySql

    Je n'ai pas le temps de décortiquer le code pour le moment mais je jette un oeil plus concentré ce soir pour essayer de comprendre la requête et l'erreur.

  10. #10
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    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 818
    Billets dans le blog
    14
    Par défaut
    Effectivement, il y a une ligne en trop dans ma requête ! Voilà ce que c'est de ne pas se relire attentivement !
    Supprime le premier LEFT OUTER JOIN.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    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 !

  11. #11
    Membre averti
    Inscrit en
    Mai 2008
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 17
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT tmp.id_sujet
    FROM
    (
        SELECT a.id_mbr AS mbr, s.id AS id_sujet, s.last_msg AS msg
        FROM sujets s
        INNER JOIN adhesion a ON a.id_gpe = s.id_gpe
        WHERE a.id_mbr = 1
            AND a.etat = 1
    ) tmp 
    LEFT OUTER JOIN derniereVisite d 
        ON d.id_mec = tmp.mbr
        AND d.id_sujet = tmp.id_sujet
    WHERE tmp.msg > d.quand
        OR d.id IS NULL
    ORDER BY tmp.msg ASC
    Avec 2-3 corrections: suppression de la ligne id_gpe = 144 (c'était pour l'exemple, maintenant on regarde dans tous les sujets de tous les groupes)
    tmp.id_sujet au lieu de tmp.id, j'ai mis des alias sur toutes les colonnes de la première table.
    Et j'ai rajouté un ORDER BY histoire que ça soit cohérent.

    Et c'est maintenant que je te dis un gros gros gros merci!!! Je vais pouvoir décortiquer cette requête histoire de comprendre.
    Merci infiniment!

  12. #12
    Membre averti
    Inscrit en
    Mai 2008
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 17
    Par défaut
    Bonsoir bonsoir!!

    Je reviens à la charge après avoir fait évoluer ma requête! Aujourd'hui j'ai ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    SELECT tmp.id_sujet AS id, tmp.titre AS titre, tmp.gpe AS gpe, tmp.evt AS evt
    	FROM
    	(
    	SELECT
    	    s.id AS id_sujet,
    	    s.titre AS titre,
    	    s.last_msg AS msg,
    	    s.id_gpe AS gpe,
    	    s.id_evt AS evt
    	FROM
    	    sujets s
    	WHERE
    	   s.id_gpe IN (SELECT id_gpe FROM adhesion WHERE id_mbr = '%s' AND etat = 1 AND alerte = 1)
    	OR
    	   s.id_evt IN (SELECT id_evt FROM evt_rep WHERE id_mbr = '%s' AND reponse = 1)
    	ORDER BY s.id_gpe, s.id_evt ASC
    	) tmp
    	LEFT OUTER JOIN derniereVisite d
    	ON d.id_mec = '%s'
    	AND d.id_sujet = tmp.id_sujet
    	WHERE tmp.msg > d.quand
    	OR d.id IS NULL
    	ORDER BY tmp.msg ASC
    La requête est bonne j'obtiens tout pile ce que je veux mais le soucis c'est qu'elle est super lourde et donc super lente!! (Environ 7 secondes d'exécution...)

    Je suis persuadé qu'il y a moyen de l'optimiser. J'avais une version avec des jointures qui me donnait une erreur de MAX_JOIN_SIZE rows surement parce qu'elle était fausse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    SELECT tmp.id_sujet AS id, tmp.titre AS titre
     FROM
     (
     SELECT
         a.id_mbr AS mbr,
         s.id AS id_sujet,
         s.titre AS titre,
         s.last_msg AS msg,
         s.id_gpe AS gpe,
         s.id_evt AS evt
     FROM
         sujets s
     JOIN
         adhesion a
     ON
         (a.id_gpe = s.id_gpe AND a.etat = 1 AND a.alerte = 1)
     JOIN
         evt_rep e
     ON
         (e.id_evt = s.id_evt AND e.reponse = 1)
     WHERE
         a.id_mbr = '%s'
     OR
         e.id_mbr = '%s'
     ORDER BY s.id_gpe, s.id_evt
     ) tmp
     LEFT OUTER JOIN derniereVisite d
     ON d.id_mec = tmp.mbr
     AND d.id_sujet = tmp.id_sujet
     WHERE tmp.msg > d.quand
     OR d.id IS NULL
     ORDER BY tmp.msg ASC
    Mais je rame beaucoup plus avec les jointures, je les ai découvertes il y a 3 semaines ^^

    Pour bien comprendre, je rajoute à la situation précédente des sujets contenus dans des événements auxquels l'utilisateur participe.

    Avec "evt_rep"
    | id | id_mbr | id_evt | reponse |
    |key | INT | INT | 0/1/2 |

    (reponse : 0 -> n'y va pas, 1 -> y va, 2 -> peut-être; on ne gardera que reponse = 1)

    Et dans la table sujets on rajoute une colonne id_evt en précisant que quand id_gpe != 0, id_evt = 0 et inversement.

    Merci de l'attention que vous porterez à mon message!!

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

Discussions similaires

  1. Problème de requête SQL avec instruction TRANSFORM
    Par Nosper dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 21/06/2005, 16h15
  2. problème de requète SQL pour formulaire
    Par en_stage dans le forum Requêtes et SQL.
    Réponses: 15
    Dernier message: 21/06/2005, 12h21
  3. [SQL] Problème de requête SQL de plus de 8060 caractères ?
    Par webtheque dans le forum MS SQL Server
    Réponses: 13
    Dernier message: 06/04/2005, 15h07
  4. [SQLserver2000][SQLServer CE] problème de requête SQL
    Par JBernn dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 27/01/2005, 09h29
  5. Problème de requète SQL dans un Requery
    Par Keraccess dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 22/10/2004, 14h58

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