Partage
  • Partager sur Facebook
  • Partager sur Twitter

reqûete pourtant simple dans ma tête mais...

    1 octobre 2024 à 9:08:46

    Hello, 

    je galère depuis hier sur une requête et je comprends pas pourquoi.

    J'ai une table simple avec id, title, receiver, sender, date

    Je veux obtenir le dernier message reçu pour un receiver.

    donc je fais un 

    select *
    from message
    where receiver = xxx
    group by sender
    order by id desc

    mais en fait ça ne resort que le 1er message par sender.

    Est-ce que quelqu'un sait me dire où je me déchire?

    Merci d'avance

    • Partager sur Facebook
    • Partager sur Twitter
      1 octobre 2024 à 13:21:02

      vu que tu groupes par sender, la requête n'en conserve qu'un seul, si tu veux le dernier tu devrais ordonner par la date et non pas par l'id

      https://sql.sh/cours/group-by 

      -
      Edité par umfred 1 octobre 2024 à 13:21:54

      • Partager sur Facebook
      • Partager sur Twitter
        1 octobre 2024 à 14:23:08

        Merci de ta réponse Umfred !!

        Malheureusement, ça ne change rien.

        Voici une capture du résultat sans le group by

        et voici quand je rajoute le group by sender

        Normalement, au vu des données ce sont les id 6 et 5 (voir capture précédente) qui devraient ressortir 

        Voici ma requête

        select *
        from notification n
        where n.receiver_id = 525
        group by n.sender_id
        order by n.created_at DESC

        Si tu vois quelques choses que je ne vois pas, je suis preneur.

        Merci d'avance.

        Sam

        -
        Edité par meeyo 1 octobre 2024 à 14:39:03

        • Partager sur Facebook
        • Partager sur Twitter
          1 octobre 2024 à 14:31:27

          tu as du le voir mais les images ne passent pas (il ne faut pas les ajouter par copier/coller), modifie ton post pour corriger ça (et relie ma réponse qui était en 2 parties (pas forcément bien séparées je l'avoue))

          -
          Edité par umfred 1 octobre 2024 à 14:34:08

          • Partager sur Facebook
          • Partager sur Twitter
            1 octobre 2024 à 15:03:21

            Hello, j'ai modifié mon post.

            J'ai relu ta réponse mais pas sur de distinguer les 2 parties. Je fais bien un order par la date maintenant.

            Sam

            • Partager sur Facebook
            • Partager sur Twitter
              1 octobre 2024 à 15:59:00

              je pense qu'il faut faire une 1ère requête qui classe par date puis faire le regroupement

              select *
              from (select * from notification order by created_at desc)
              where receiver_id = 525
              group by sender_id
              



              • Partager sur Facebook
              • Partager sur Twitter
                3 octobre 2024 à 9:17:15

                > mais en fait ça ne resort que le 1er message par sender.

                > Est-ce que quelqu'un sait me dire où je me déchire?

                Ce qu'on veut - si j'ai bien compris - c'est la notification du message le plus récent obtenu par un "receiver".

                C'est "tous senders confondus", donc il n'y a pas de raison que le champ sender apparaisse dans la requête.

                Essayons avec sqlite

                Création de la table

                CREATE TABLE IF NOT EXISTS "notification" (
                	"message_id"	INTEGER NOT NULL UNIQUE,
                	"title"	TEXT NOT NULL,
                	"receiver"	TEXT NOT NULL,
                	"sender"	TEXT NOT NULL,
                	"date"	TEXT NOT NULL,
                	PRIMARY KEY("message_id")
                );
                
                

                j'ai interprété "id" comme étant l'identifiant du message notifié, pas celui de la notification.

                La table contient quelques données

                INSERT INTO "notification" VALUES (9,'un','bob','anna','2024-10-02');
                INSERT INTO "notification" VALUES (10,'deux','charlie','bob','2024-10-03');
                INSERT INTO "notification" VALUES (11,'trois','anna','charlie','2024-10-04');
                INSERT INTO "notification" VALUES (12,'quatre','charlie','anna','2024-10-05');
                INSERT INTO "notification" VALUES (13,'cinq','bob','charlie','2024-10-06');
                INSERT INTO "notification" VALUES (14,'six','anna','bob','2024-10-07');
                

                Procédons avec douceur, calme, avec méthode, étape par étape.

                1. Les messages reçus par tout le monde

                sqlite> .mode column
                sqlite> select * from notification;
                message_id  title   receiver  sender   date      
                ----------  ------  --------  -------  ----------
                9           un      bob       anna     2024-10-02
                10          deux    charlie   bob      2024-10-03
                11          trois   anna      charlie  2024-10-04
                12          quatre  charlie   anna     2024-10-05
                13          cinq    bob       charlie  2024-10-06
                14          six     anna      bob      2024-10-07
                

                2. ceux reçus par anna

                sqlite> select * from notification
                   ...> where receiver = "anna";
                message_id  title  receiver  sender   date      
                ----------  -----  --------  -------  ----------
                11          trois  anna      charlie  2024-10-04
                14          six    anna      bob      2024-10-07
                


                3. Dans l'ordre du plus récent d'abord

                sqlite> select * from notification
                   ...> where receiver = "anna"
                   ...> order by date desc;
                message_id  title  receiver  sender   date      
                ----------  -----  --------  -------  ----------
                14          six    anna      bob      2024-10-07
                11          trois  anna      charlie  2024-10-04
                

                4. Si le premier seulement voir tu voudras

                sqlite> select * from notification
                   ...> where receiver = "anna"
                   ...> order by date desc
                   ...> limit 1
                   ...> ;
                message_id  title  receiver  sender  date      
                ----------  -----  --------  ------  ----------
                14          six    anna      bob     2024-10-07
                


                Bref, en français : la plus récente notification destinée à "anna".

                Et pourquoi tu coinces : parce que tu as décidé au feeling qu'il fallait coller un "group by" dans ta requête. Alors que non.

                • les plus récentes d'abord = order by date desc
                • LA plus récente = limit 1

                -
                Edité par michelbillaud 3 octobre 2024 à 20:38:38

                • Partager sur Facebook
                • Partager sur Twitter
                  4 octobre 2024 à 13:21:41

                  Hello, 

                  merci du temps que tu as pris!

                  Mais en effet, je veux le dernier message qu'un receiver a reçu de chacun de ses sender.

                  Dans ton exemple, je veux le dernier message que bob a envoyé à Anna et aussi le dernier message que Charlie a envoyé à Anna

                  A dispo

                  Sam

                  • Partager sur Facebook
                  • Partager sur Twitter
                    4 octobre 2024 à 19:42:07

                    Bon alors le plus récent message que chaque envoyeur a expédié à XXX, c'est une autre histoire (et je sais pas faire simplement - mais je ne suis pas une référence)

                    EDIT

                    Ah si, une idée, en laissant tomber le truc du order/limit 1

                    On veut les notifications destinées à anna, pour lesquelles il n'existe pas d'autre notification plus récente du même envoyeur. Une requête imbriquée, where not exists...

                    select * from notification as n1
                    where receiver = "anna"
                    and not exists (select * from notification as n2
                                    where n2.receiver = "anna"
                    				and   n2.sender   = n1.sender
                    				and   n2.date > n1.date
                    				);

                    Testé en ajoutant quelques données

                    sqlite> .mode column
                    sqlite> select * from notification;
                    message_id  title   receiver  sender   date      
                    ----------  ------  --------  -------  ----------
                    9           un      bob       anna     2024-10-02
                    10          deux    charlie   bob      2024-10-03
                    11          trois   anna      charlie  2024-10-04
                    12          quatre  charlie   anna     2024-10-05
                    13          cinq    bob       charlie  2024-10-06
                    14          six     anna      bob      2024-10-07
                    15          sept    anna      charlie  2024-10-08
                    16          huit    anna      charlie  2024-10-09
                    17          neuf    anna      charlie  2024-10-10
                    18          six     anna      bob      2024-10-11
                    sqlite> 
                    

                     la requête

                    sqlite> select * from notification as n1
                       ...> where receiver = "anna"
                       ...>         and not exists (select * from notification as n2
                       ...>                         where n2.receiver = "anna"
                       ...>                         and   n2.sender   = n1.sender
                       ...>                         and   n2.date > n1.date
                       ...>                         );
                    message_id  title  receiver  sender   date      
                    ----------  -----  --------  -------  ----------
                    17          neuf   anna      charlie  2024-10-10
                    18          six    anna      bob      2024-10-11
                    sqlite> 
                    


                    Aucune garantie sur les performances.

                    Faut pas non plus que deux messages avec même envoyeur et expéditeur soient exactement à la même date, enfin en prenant des dates en milli ou micro secondes, ça devrait pas arriver (cross fingers)

                    Il est possible que ça s'exprime aussi à coup de left join ou inner join, mais ça m'a toujours fait mal à la tête.   Ce que j'aurais bien aimé, c'est factoriser
                    select * from notifcation where receiver = "anna";

                    qui apparait 2 fois

                    -
                    Edité par michelbillaud 5 octobre 2024 à 8:44:36

                    • Partager sur Facebook
                    • Partager sur Twitter
                      5 octobre 2024 à 9:39:15

                      Hello Michel! 

                      C'est carrément une bonne piste! 

                      Merci beaucoup, je vais continuer de creuser le sujet

                      Bon weekend

                      • Partager sur Facebook
                      • Partager sur Twitter

                      reqûete pourtant simple dans ma tête mais...

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      • Editeur
                      • Markdown