[SQL] comparaison Résultat

Résolu
Bonjour,

Je travaille en SQL et je précise que je ne peux pas utiliser autre chose.

En fait mon problème est que je retourne un résultat du type :

ID secondaire | Commentaire
1 | Commentaire1
1 | Commentaire2
1 | Commentaire3
2 | Commentaire1
... | ...

Et je voudrais faire une requête qui me permettrait de comparer le résultat de l'ID secondaire avec le suivant (ici d'abord 1 avec 1, puis 1 avec 1, puis 1 avec 2 ... etc... )

Et n'afficher un résultat que lorsque les deux sont différents

(Donc en clair ça doit m'afficher le dernier commentaire de chaque ID secondaire.

Je sais pas si c'est très clair... ^^"

Demandez moi si vous voulez plus de précisions.

Merci d'avance pour vos réponses =)

26 réponses

Résumé de la discussion

La problématique porte sur l'extraction du dernier commentaire par ID secondaire dans un jeu de résultats SQL où chaque ID secondaire peut apparaître plusieurs fois avec des commentaires différents. Plusieurs réponses suggèrent d'isoler le dernier commentaire de chaque ID secondaire à l'aide d'une sous-requête ou d'un TOP 1 avec tri par le champ commentaire, afin d'obtenir une ligne par identifiant. En pratique, des difficultés apparaissent lorsque l'ID est text et nécessite une conversion vers int via Convert(int, …), avec des GROUP BY ou des conversions dans les sous-requêtes pour permettre le tri. Des détails pratiques évoquent l'impossibilité de trier des champs text sans conversion et les limites liées à l'utilisation de TOP 1 selon l'environnement SQL, ainsi que des conseils pour tester localement les résultats.

Bobot (l’IA à votre service)
  1. J'ai rien compris XD
    1. Contributeur
      Oups, j'avais cru que ça avait pas afficher, désolé :s
      1. Il bug le forum. Le problème de WHERE c'est qu'il ne compare qu'une valeur et donc ne retourne souvent qu'une poignée de champ sans forcement en garder un de chaque.

        C'est clair que sans avoir les tables complètes, c'est dur de construire une requête car tu ne connais pas toutes les possibilités. Je ne savais même pas qu'il y avait un champ de date. :P

        Bravo pour ta belle requête et bon courage ^^
    2. Contributeur
      J'ai enfin réussi ! ! ! :D
      J'ai utilisé le champ date (qui ici s'appelle system_time)

      Je post la requête si ça peut aider quelqu'un plus tard ! =)

      Encore merci à toi X-Fan et @bientôt! =)

      Voici la requête finale :

      SELECT
      Convert(int, t2.ref_num) "Ref_Num",
      t1.description,
      t1.system_time

      FROM
      Act_log "t1",
      call_req "t2"

      WHERE
      t1.type = 'LOG'
      AND t1.call_req_id = t2.persid
      AND t2.ref_num >= '105410'
      AND t2.ref_num <= '105420'
      AND t1.system_time IN (
      SELECT
      MAX(t1.system_time) AS "sys_time_max"
      FROM
      Act_log "t1",
      call_req "t2"
      WHERE
      t1.type = 'LOG'
      AND t1.call_req_id = t2.persid
      AND t2.ref_num >= '105410'
      AND t2.ref_num <= '105420'
      GROUP BY
      t2.ref_num
      )

      ORDER BY
      t2.ref_num
      1. Contributeur
        Bon, j'ai finalement réussi ! ! ! :D

        En utilisant le champ date.

        Voici ma requête finale :

        SELECT
        Convert(int, t2.ref_num) "Ref_Num",
        t1.description,
        t1.system_time

        FROM
        Act_log "t1",
        call_req "t2"

        WHERE
        t1.type = 'LOG'
        AND t1.call_req_id = t2.persid
        AND t2.ref_num >= '105410'
        AND t2.ref_num <= '105420'
        AND t1.system_time IN (
        SELECT
        MAX(t1.system_time) AS "sys_time_max"
        FROM
        Act_log "t1",
        call_req "t2"
        WHERE
        t1.type = 'LOG'
        AND t1.call_req_id = t2.persid
        AND t2.ref_num >= '105410'
        AND t2.ref_num <= '105420'
        GROUP BY
        t2.ref_num
        )

        ORDER BY
        t2.ref_num

        Merci encore pour ton aide ! =)

        A bientôt
        1. Contributeur
          Bonjour,

          Et bien j'ai encore un problème ! :D

          Il me dit que, pour être dans le HAVING, le t2.ref_num doit être dans un GROUP BY.

          Le problème c'est que si je met t2.ref_num dans un GROUP BY, il me dit qu'il faut que j'y mette aussi t1.persid et t1.description.
          Mais en fait, il ne veut pas de champ text dans le GROUP BY! xD

          Donc en fait je tourne en rond un peu ... ^^

          Je ne peux pas le mettre dans un WHERE plutôt que dans un HAVING?

          Sinon j'ai un champ date dans ma table t1 (c'est un timestamp je crois, il a une valeur en moyenne de 1 206 xxx xxx ).
          Ca peut aider?

          Ah oui et je me demandais : à quoi ça sert tes "xx" à la fin de ton HAVING?

          EDIT :
          Je viens d'enlever le GROUP BY que j'avais rajouté et de remplacer le HAVING par un WHERE.

          Il ne m'affiche qu'un seul commentaire, et même pas le dernier :(
          Le problème avec ton TOP 1 c'est qu'il ne m'affichera toujours qu'un résultat... :s
          1. Ouai ben voilà alors..

            on a:
            matable1 "t1" :
            t1.persid, t1.description

            matable2 "t2" :
            t2.persid, t2.ref_num

            Donc:

            SELECT TOP 1 t1.persid, t1.desciption FROM matable1 t1
            INNER JOIN matable2 t2
            ON t1.persid = t2.persid
            HAVING t2.ref_num = (SELECT DISTINCT(t3.ref_num) FROM matable2 t3) xx
            ORDER BY t1.persid DESC

            Essaie de quoi du genre d'abord.
            1. Contributeur
              Bon, il m'a fallu de la concentration mais j'ai compris et tu expliques bien tkt =)

              Et moi je veux afficher :

              1, bonjour
              2, je suis là

              J'ai compris comment fonctionne le inner join mais je ne vois pas comment il peut m'afficher le résultat que je veux xD
              1. ok merci mon chou, ça va déjà être plus facile comme ça XD

                Alors je te montre comment marche inner join. Inner join sert à joindre deux tables ayant des champs en commun.

                Donc, il va te sortir de l'information pour tous les champs ayant une valeur égale selon le champ de référence.

                si j'ai la table:

                matable t1 avec les deux champs id, description et qui contient les lignes suivantes:
                a1, salut
                a1, bonjour
                a2, je suis là
                a3, blabla

                matable t2 avec les deux champs id, ref et qui contient les lignes suivantes:
                a1, 1
                a2, 2
                a3, 3

                Si je vais une inner join, la table virtuel qui va se créer aura l'air de:
                a1, salut, 1
                a1, bonjour, 1
                a2, je suis là, 2
                a3, blabla, 3

                Si maintenant je reprend ma table t1 et que je fais un inner join avec ma table t3
                matable t3 avec les deux champs id, ref et qui contient les lignes suivantes:
                a1, 1
                a2, 2

                le résultat de la table virtuel sera:
                a1, salut, 1
                a1, bonjour, 1
                a2, je suis là, 2

                Est-ce que tu comprends ou j'explique mal XD ?

                Bien entendu, il y a aussi LEFT JOIN, RIGHT JOIN ET FULL JOIN mais bon, pense pas qu'on en aura besoin.
                1. Contributeur
                  Voilà, enfin presque mais ça revient au même ^^

                  On va les appeler :

                  matable1 "t1" :
                  t1.persid, t1.description

                  matable2 "t2" :
                  t2.persid, t2.ref_num
                  1. Ok donc tu as

                    matable 1
                    idsecondaire, commentaire

                    matable 2
                    idsecondaire, mêmenumerosansleslettres

                    C'est ça?
                    1. Contributeur
                      Oui oui, il vient d'une autre table mais pas de problème pour l'intégrer et il correspond à l'id secondaire du début mais avec la contrainte du text en moins.
                      1. c'est quoi ton champ qui est seulement numérique là ? Et est-ce que c'est toujours la même valeur pour un même idsecondaire (donc on pourrait l'utiliser pour travailler comme si on utilisait le idsecondaire)?
                        1. Contributeur
                          Sinon, en adaptant ce que tu m'a proposé pour qu'il n'y ait plus d'erreur j'arrive à ça :

                          SELECT
                          Convert(int, t2.ref_num) "Ref_Num",
                          t1.description
                          FROM
                          Act_log "t1",
                          call_req "t2"
                          WHERE
                          t1.type = 'LOG'
                          AND t1.call_req_id = t2.persid
                          AND t2.ref_num >= '105410'
                          AND t2.ref_num <= '105420'
                          AND Convert(int,t2.ref_num) IN
                          (SELECT DISTINCT Convert(int, t3.ref_num)
                          FROM
                          call_req "t3"
                          WHERE
                          t3.ref_num >= '105410'
                          AND t3.ref_num <= '105420'
                          GROUP BY Convert(int, t3.ref_num))
                          ORDER BY Convert(int, t2.ref_num)

                          Mais ça ne m'affiche pas ce que je veux...

                          Ca m'affiche les ID avec tous les commentaires pour chaque ID.
                          1. INNER JOIN ne sert qu'à lier deux tables sur un champ commun. Tu n'es pas supposé de retirer de l'information avec cette clause. C'est la clause HAVING ou WHERE qui doit servir à sélectionner des enregistrements filtrés.
                          2. Contributeur
                            @X-FanD'accord, donc on oublie le INNER JOIN pour cette question.

                            Tu as une idée pour afficher seulement le dernier commentaire?

                            Parce que moi à part comparer la valeur du ref_num avec la valeur suivante je vois pas ..
                        2. Contributeur
                          Non, il ne substring ne fonctionne pas mais en fait je n'en ai pas besoin : j'utilise un autre champ qui ne comporte que des chiffres donc plus de problème de ce côté là.

                          Je n'ai même plus de problème pour la conversion en integer.

                          J'ai trouvé sur un autre forum une personne qui avait un problème un peu similaire.

                          En essayant d'adapter son code j'arrive à ça mais toujours quelques soucis : il me dit que la colonne ref_num est invalide.
                          Je ne sais pas trop utiliser l'inner join donc bon ... :s

                          SELECT
                          Convert(int, t2.ref_num) "Ref_Num",
                          t2.description
                          FROM
                          call_req "t2",
                          Act_log "t1"
                          INNER JOIN
                          (
                          SELECT
                          Max(t1.ref_num),
                          t2.id
                          FROM
                          Act_log "t1",
                          call_req "t2"
                          WHERE
                          t1.type = 'LOG'
                          AND t1.call_req_id = t2.persid
                          GROUP BY
                          t1.id
                          ) As "DernierEnrs"
                          ON t1.id=DernierEnrs.id
                          AND t1.ref_num=DernierEnrs.ref_num
                          WHERE
                          t1.type = 'LOG'
                          AND t1.call_req_id = t2.persid
                          GROUP BY t2.id
                          1. Tu peux mettre:
                            GROUP BY Convert(int, t3.ref_num)

                            Je ne pense pas que ce soit interdit. Mais sinon, est-ce que tu as pu faire marcher substring?
                            1. Contributeur
                              Bonjour,

                              Je viens de tester la fonction convert et dans mon logiciel, elle ne fonctionne pas comme en SQL normal.

                              Pour convertir en integer je doit faire : Convert(int, t2.ref_num)

                              Comme ça, la conversion fonctionne mais par contre le reste non ^^

                              J'ai pû faire fonctionner la sous-requête mais là où il y a un problème c'est au niveau du :
                              Convert(int, t2.ref_num) = (SELECT DISTINCT Convert(int, t3.ref_num) 'Ref_Num_Test' FROM call_req AS "t3")

                              Comme il est dans un HAVING, je dois mettre t2.ref_num dans un GROUP BY avant.

                              Seulement le problème est que lorsque je met le t2.ref_num dans un GROUP BY, il me dit qu'il ne peut pas trier des champs text (il ne prend pas la conversion dans le GROUP BY ... )
                              1. SELECT TOP 1 m.idsecondaire, m.commentaire FROM matable m
                                HAVING CONVERT((CONVERT(SUBSTR(m.idsecondaire,3,LEN(m.idsecondaire)) AS varchar(10))) AS int) = (SELECT DISTINCT(CONVERT((CONVERT(SUBSTR(m2.idsecondaire,3,LEN(m2.idsecondair­e)) AS varchar(10)) AS int))) FROM matable m2) xx
                                ORDER BY m.commentaire DESC

                                Un truc comme ça je suppose.
                                1. SELECT m.idsecondaire, m.commentaire FROM matable m
                                  INNER JOIN (SELECT TOP 1 * FROM matable m2 ORDER BY commentaire DESC )xx
                                  ON xx.idsecondaire = m.idsecondaire

                                  J'ai franchement pas d'idées là tout de suite LOL. Faut que j'y pense mais bref.
                                  1. Contributeur
                                    Mon champ call_req_id est toujours de la forme "cr:xxxxxx".

                                    Je me demande donc si on peut pas avec SQL virer les "cr:" puis transformer le résultat en int.

                                    Ou alors comparer le résultat au suivant (mais toujours le même problème en fait ... ^^ )
                                    1. Toujours des numéros après les deux points?
                                    2. Contributeur
                                      @X-FanOui, toujours une suite de 6numéros.
                                    3. @X-FanAlors dans ce cas:

                                      SELECT TOP 1 m.idsecondaire, m.commentaire FROM matable m
                                      HAVING CONVERT(SUBSTR(m.idsecondaire,3,LEN(m.idsecondaire)) AS int) = (SELECT DISTINCT(CONVERT(SUBSTR(m2.idsecondaire,3,LEN(m2.idsecondaire)) AS int)) FROM matable m2) xx
                                      ORDER BY m.commentaire DESC
                                    4. Contributeur
                                      @X-FanJe viens d'essayer les 2 que tu m'as proposé ... Toujours une erreur.

                                      Par contre pour le dernier l'erreur est diférente : il me dit qu'il y a une erreur de syntaxe près de "," (je sais pas quel virgule par contre >< )

                                      Voici comment je l'ai adapté, tu trouveras peut-être l'erreur :

                                      SELECT TOP 1
                                      t1.call_req_id,
                                      t1.action_desc
                                      FROM
                                      Act_log AS "t1"
                                      HAVING
                                      CONVERT(SUBSTR(t1.call_req_id,3,LEN(t1.call_req_id)) AS int) = (SELECT
                                      DISTINCT(CONVERT(SUBSTR(t2.call_req_id,3,LEN(t2.call_req_id)) AS int))
                                      FROM
                                      Act_log AS "t2") xx
                                      ORDER BY t1.action_desc DESC
                                    5. @Passarinho44Le meilleur moyen de savoir c'est de commencer par exécuter celle là toute seule:

                                      SELECT
                                      DISTINCT(CONVERT(SUBSTR(t2.call_req_id,3,L­EN(t2.call_req_id)) AS int))
                                      FROM
                                      Act_log AS "t2"

                                      Voir si elle marche et si le résultat retourné est celui désiré.
                                  2. J'y pense mais la clause HAVING ne fonctionne pas avec texte donc il faut trouver autre chose ;)
                                    • 1
                                    • 2