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 :

Requêtes imbriquées à trois niveaux


Sujet :

Langage SQL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut Requêtes imbriquées à trois niveaux
    Bonjour à tous,

    Ceci sera mon seul et unique appel. Sans réponse à ce message, j'envisagerai sérieusement de me jeter dans l'escalier. Tant pis. Fin de l'histoire.

    Ca fait 3 jours que je me bats avec une requête (sous MySQL 5.1, en l'occurrence, mais je doute que le chimilblic vienne de là).

    La requête (simplifiée à mort (d'où le 1=1), mais le problème est isolé) :

    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
     
    SELECT  MAIN_url.Id 
     
    FROM url AS MAIN_url 
     
    WHERE   
                 1 = 1
     
            AND
     
                 (   
                      SELECT COUNT( *) 
                      FROM ( 
                              SELECT Valide 
                              FROM commentaire 
                              WHERE IdUrl = MAIN_url.Id
                              ORDER BY DateCommentaire DESC 
                              LIMIT 0, 2 
                            ) AS Plus_recent_commentaire
                      WHERE Valide = 1
                 ) >= 1
    La tentative d'exécution dudit code me renvoie à l'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur : SQLSTATE[42S22]: Column not found: 1054 Unknown column 'MAIN_url.Id' in 'where clause'
    Il semble ne pas vouloir, dans le SELECT le plus imbriqué, récupérer la table MAIN_url du SELECT le moins imbriqué.

    J'ai essayé de contourner le problème en formulant ma requête différemment. Mais je n'y arrive pas.

    La personne qui me sortira de ce mauvais pas, aura le droit, à sa convenance :
    - à ma gratitude infinie pendant plusieurs heures consécutives
    - à une vidéo de moi-même me flagellant
    - à un massage des pieds, même sales

    Je suis près à tout, ptdrrrrrr. J'vais craquer....

  2. #2
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    tu es dans la pub ? en voila un titre choc

    et comme cela ?
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT Main_Url.Id
      FROM Url AS Main_Url
      WHERE 1 = 1
              AND EXISTS(SELECT COUNT(*) AS Nb
                           FROM (SELECT Valide
                                   FROM Commentaire
                                   WHERE Commentaire.Idurl = Main_Url.Id
                                   ORDER BY Datecommentaire DESC Limit 0, 2) AS Plus_Recent_Commentaire
                           WHERE Plus_Recent_Commentaire.Valide = 1 HAVING COUNT(*) > 1)


    si ca marche, j'attends la
    Merci d'ajouter un sur les tags qui vous ont aidé

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par dehorter olivier Voir le message
    si ca marche, j'attends la
    Ptdrrrrrr, tu préfères pas que je m'occupe de tes pieds ?

    Bon, j'essais ta requête...

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Olivier, olivier, olivier...

    Ta requête retourne la même erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Unknown column 'Main_Url.Id' in 'where clause'
    J'ai vraiment du mal sur ce coup....

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingenieur de recherche - Ecologue
    Inscrit en
    Juin 2003
    Messages
    1 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingenieur de recherche - Ecologue

    Informations forums :
    Inscription : Juin 2003
    Messages : 1 146
    Points : 1 412
    Points
    1 412
    Par défaut
    j'ai un peu modifié la requête

    et ça marche chez moi (attention pas sous mysql)

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT Main_Url.Id
      FROM Url AS Main_Url
      WHERE 1 = 1
              AND EXISTS(SELECT COUNT(*) AS Nb
                           FROM (SELECT Valide
                                   FROM Commentaire
                                   WHERE Commentaire.Idurl = Main_Url.Id
                                           AND Commentaire.Valide = 1
                                   ORDER BY Datecommentaire DESC Limit 0, 2) AS Plus_Recent_Commentaire
                           HAVING COUNT(*) > 1)
    Merci d'ajouter un sur les tags qui vous ont aidé

  6. #6
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 576
    Points
    2 576
    Par défaut
    En dehors de tout problème syntaxique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ... EXISTS(SELECT COUNT(*) ...
    Est toujours vrai si je ne m'abuse.

    Vous devriez déjà donner la structure des tables, un jeu de données exemple et le résultat attendu.

    Edit : J'avais pas vu le having

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    La requête ne veut plus dire la même chose:

    - le 2ème SELECT>=1 doit vérifier si il y a au moins 1 commentaire valide parmi les 2 plus récents.

    - La requête, telle que vous la proposez, retourne les 2 commentaires valides les plus récents.

    Cependant, mis à part ce point de détail, le test de votre requête aboutie, chez moi (MySQL 5.1) à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Unknown COLUMN 'Main_Url.Id' IN 'where clause'

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    D'ailleurs, j'avais une erreur dans ma première requête... il faut pas travailler fatigué.

    J'ai édité ma première requête pour remplacer l'ancien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    (   
        SELECT COUNT(*) 
        FROM (  
            SELECT ...
        ) 
        WHERE Valide=1
    ) > 1
    Par le code correct (">=1" au lieu de ">1"):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    (   
        SELECT COUNT( *) 
        FROM (  
            SELECT ...
        ) 
        WHERE Valide=1
    ) >= 1
    Ca ne corrige pas, bien-sûr, l'erreur retournée...

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Je représente mon problème avec un jeu de données d'essais.

    La requête est :
    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
     
    SELECT  MAIN_url.Id 
    FROM url AS MAIN_url 
    WHERE   
                 1 = 1
            AND
                 (   
                      SELECT COUNT( *) 
                      FROM ( 
                              SELECT Valide 
                              FROM commentaire 
                              WHERE IdUrl = MAIN_url.Id
                              ORDER BY DateCommentaire DESC 
                              LIMIT 0, 2 
                            ) AS Plus_recent_commentaire
                      WHERE Valide = 1
                 ) >= 1
    Les tables et leurs jeux de données sont :

    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
     
    |Table url
    +----+----------------------+
    | Id | URL                  |
    +----+----------------------+
    |  0 | www.mystere.com      |
    |  1 | www.et-boule.com     |
    |  2 | www.de-gomme.com     |
    |  3 | www.blablab.com      |
    |  4 | www.google2.com      |
    +----+----------------------+
     
    |Table commentaire
    +----+-------+------------------+-----------------+--------+
    | Id | IdURL | Commentaire      | DateCommentaire | Valide |
    +----+-------+------------------+-----------------+--------+
    |  0 |     1 | Trop bien ce...  | 2012-06-12      |      0 |
    |  1 |     2 | J'ai adoré l...  | 2012-07-01      |      1 |
    |  2 |     1 | C'est pourri...  | 2012-07-01      |      1 |
    |  3 |     3 | Il faudrait ...  | 2012-07-02      |      1 |
    |  4 |     3 | Pas de style...  | 2012-07-05      |      1 |
    |  5 |     3 | Le mec il cr...  | 2012-07-14      |      0 |
    |  6 |     3 | PTTTTTTDDDRR...  | 2012-07-15      |      1 |
    |  7 |     2 | R.A.S. !!!!!...  | 2012-07-22      |      0 |
    +----+-------+------------------+-----------------+--------+

    --------------------------------------------------------------------------------


    La requête la plus imbriquée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
                              SELECT Valide 
                              FROM commentaire 
                              WHERE IdUrl = MAIN_url.Id
                              ORDER BY DateCommentaire DESC 
                              LIMIT 0, 2
    devrait retourner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    +--------+
    | Valide |
    +--------+
    |      0 |
    |      1 |
    sur la base des lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    |Table commentaire
    +----+-------+------------------+-----------------+--------+
    | Id | IdURL | Commentaire      | DateCommentaire | Valide |
    +----+-------+------------------+-----------------+--------+
    |  5 |     3 | Le mec il cr...  | 2012-07-14      |      0 |
    |  6 |     3 | PTTTTTTDDDRR...  | 2012-07-15      |      1 |

    --------------------------------------------------------------------------------


    La requête intermédiaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
                      SELECT COUNT( *) 
                      FROM ( 
                              REQUETE-IMBRIQUE 
                            ) AS Plus_recent_commentaire
                      WHERE Valide = 1
    devrait retourner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    +---+
    |   |
    +---+
    | 1 |
    sur la base des lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    +--------+
    | Valide |
    +--------+
    |      0 |
    |      1 |

    --------------------------------------------------------------------------------


    Le test de la requête principale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ( SELECT COUNT( *) ) >= 1
    devrait donc être vrai.


    --------------------------------------------------------------------------------


    En français :

    Il y a au moins 1 commentaire Valide parmi les 2 plus récents concernant l'URL en cours.


    Merci pour votre patience et votre aide.

  10. #10
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    445
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 445
    Points : 622
    Points
    622
    Par défaut
    Avec un peu de chance, c'est ce que tu cherches :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT COUNT(*) FROM 
    (
        SELECT Valide FROM commentaire
        JOIN url
        ON url.Id=commentaire.IdUrl
        WHERE url.URL="www.blablab.com"
        ORDER BY Datecommentaire DESC LIMIT 0, 2
    )tmp
    WHERE Valide=1

  11. #11
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 576
    Points
    2 576
    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
    16
    17
    SELECT  
        url.Id, 
        url.url
    FROM url 
    WHERE EXISTS (	SELECT 
    			c1.id
    		FROM commentaire c1
    		LEFT JOIN commentaire c2
    			ON c1.id_url = c2.idurl 
    			AND c1.id <> c2.id 
    			AND c1.DateCommentaire > c2.DateCommentaire
    		WHERE c1.idurl = url.Id
    		GROUP BY 
    			c1.id
    		HAVING count(c2.id) < 2
    		AND  SUM(c1.valide) > 0
    	)

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Fred_34 Voir le message
    Avec un peu de chance, c'est ce que tu cherches :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT COUNT(*) FROM 
    (
        SELECT Valide FROM commentaire
        JOIN url
        ON url.Id=commentaire.IdUrl
        WHERE url.URL="www.blablab.com"
        ORDER BY Datecommentaire DESC LIMIT 0, 2
    )tmp
    WHERE Valide=1
    A priori, ça le ferait, mais il faut que l'Id de l'URL soit celui en cours dans la requête principale et c'est ce passage de valeur qui ne fonctionne pas. (Il fonctionne de la requête principale à une sous-requête, mais pas de la requête principale à une sous-sous-requête...

    Pas le temps de tester tout de suite, je reviens ce soir. Merci en tout cas.

  13. #13
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 814
    Points
    17 814
    Par défaut
    La requête imbriquée n'est pas forcément pertinente. À chaque id_url vous allez refaire le boulot, sauf si l'id est passé en dur quelque part dans la requête ce dont je doute sinon il suffirait de le redescendre aussi en dur dans la sous-requête.

    La requête ne fonctionne pas car sur certains SGBD on ne peut pas descendre l'alias à plus d'un niveau.

    Le plus simple c'est de repartir du besoin.
    Voici une seule requête qui vous donne la liste des URL satisfaisant vos conditions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        select distinct t1.idURL
          from commentaire as t1
    inner join commentaire as t2
            on t2.idURL            = t1.idURL
           and t2.DateCommentaire >= t1.DateCommentaire
      group by t1.Id, t1.idURL, t1.Commentaire, t1.DateCommentaire, t1.Valide
        having count(*)      <= 2
           and sum(t2.Valide) = 1;
    Je vous laisse la décortiquer !

  14. #14
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Concernant la transmission d'Alias sur 2 niveaux, il semble bien qu'effectivement MySQL en soit incapable...

    Par ailleurs,

    J'ai lu ta requête, je me suis dis "Mouais..., à voir, il a pas dû bien comprendre ce que je voulais, par contre, bonne idée d'exploiter l'intersection".

    J'ai un peu gratté (vu que je suis une grosse b*te en SQL), bien 4 ou 5 heures au total sur ces 3 derniers jours, j'ai appris plein de trucs, c'est cool.

    J'ai testé ta requête dans tous les sens. Elle marche, il n'y a pas à tortiller...
    Je suis content qu'elle marche.

    Par contre, je suis pas content de pas la comprendre dans ses détails les plus intimes... J'ai capté l'esprit du truc, mais j'ai du mal encore à comprendre pourquoi ça ne traite que les 2 plus récentes.

    Tu me dégoûtes...

    Merci en tout cas

Discussions similaires

  1. Pb requête imbriquée
    Par ddams dans le forum Requêtes
    Réponses: 11
    Dernier message: 20/04/2004, 13h13
  2. [Requête] Faire une requête imbriquée?
    Par sekiryou dans le forum Requêtes
    Réponses: 2
    Dernier message: 17/01/2004, 23h52
  3. problème avec une requête imbriquée
    Par jaimepasteevy dans le forum Langage SQL
    Réponses: 13
    Dernier message: 05/12/2003, 11h29
  4. Requêtes imbriquées ?
    Par Ph. B. dans le forum XMLRAD
    Réponses: 7
    Dernier message: 06/05/2003, 14h19
  5. Requête imbriquée et indexes INTERBASE
    Par vadim dans le forum InterBase
    Réponses: 2
    Dernier message: 06/09/2002, 17h15

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