Bonjour à tous,
Je patoge dans la semoule depuis quelques jours sur une requete SQL, c'est avec déséspoire que je fait un post ici en éspérant pouvoir avoir une solution :
Mon code actuel ci-dessous :

"SELECT * FROM abonnement 
      INNER JOIN abonnement_client ON abonnement.email = abonnement_client.email
      INNER JOIN abonnement_historique ON abonnement_historique.id_sub = abonnement.id_sub 
      GROUP BY abonnement_historique.id_sub DESC
      ORDER BY abonnement.date_sub DESC";

Ce que je veux

Je cherche à obtenir toutes les lignes de chaque dernier "abonnement_historique.id" de chaque "abonnement"(abonnement.id_sub) en joignant les tables "abonnement" et "abonnement_client" pour obtenir les informations de celles-ci.

Ce que j'obtiens

J'obtiens bien l'historique de chaque abonnement grace au "GROUP BY" mais pas du dernier id de abonnement_historique.id.

J'attend votre aide si vous avez bien tout compris :)

2 réponses


Hello Matth,

Alors, je ne sais pas quel SGBD tu utilise, mais normalement en l'état ta requête devrait planter, parce qu'en principe le GROUP BY doit être utilisé avec une fonction d'agrégat comme COUNT() ou SUM().
Pareil pour le DESC au niveau du GROUP BY, étonnant qu'il ne fasse pas planter la requête, et à mon avis il ne sert à rien (en tout cas je n'ai jamais vu ça dans une requête).

Je pense qu'il faudrait que tu imbrique 2 requêtes en faisant un truc de ce style là :

SELECT * FROM (
      SELECT * FROM abonnement 
      INNER JOIN abonnement_client ON abonnement.email = abonnement_client.email
      INNER JOIN abonnement_historique ON abonnement_historique.id_sub = abonnement.id_sub 
      GROUP BY abonnement_historique.id_sub
) AS abo ORDER BY abo.date_sub DESC /* !!! si "date_sub" est présent dans plusieurs tables, il faudra prefixer les champs

Voilà pour l'idée, je n'ai pas testé evidement donc je ne peux te garantir le résultat, je te laisse adapter cette requête si besoin.

Alors, dans ce genre de situation, le mieux est de prendre le problème à l'envers.
Tu vas d'abord trier tes données depuis l'historique et n'en prendre qu'un par ID.

Je tiens à préciser d'avance : Il y aura une sous-requête.

Premièrement on récupère la liste des ID qui nous intéressent, on en prend qu'un par sub_id, et on ne prend que le premier :

SELECT subHisto.id FROM abonnement_historique AS subHisto
GROUP BY subHisto.id_sub 
ORDER BY subHisto.date_sub DESC;

PS : Ici, n'hésite pas à lancer la requête à côté et vérifier que tu as déjà les bons ID voulus.

On peut maintenant récupérer les id_sub qui lui sont lié et faire les jointures (mais dans l'autre sens) :

-- Ici, je met un alias pour être sûr et certain qu'on essaie pas de prendre dans la sous-requête
SELECT * FROM abonnement_historique AS histo 

-- Attention, l'ordre est important ici
INNER JOIN abonnement ON histo.id_sub = abonnement.id_sub 
INNER JOIN abonnement_client ON abonnement.email = abonnement_client.email

WHERE histo.id IN (
  SELECT subHisto.id FROM abonnement_historique AS subHisto
  GROUP BY subHisto.id_sub 
  ORDER BY subHisto.date_sub DESC
)

-- On trie à nouveau pour l'ordre d'affichage
ORDER BY histo.date_sub DESC;

Tu devrais maintenant avoir la dernière ligne de chaque abonnement avec les informations clients qui lui sont liées.

Après, à partir du moment où tu as ton tri, tu peux faire la requête dans le sens que tu préfères :

SELECT * FROM abonnement
      INNER JOIN abonnement_client ON abonnement.email = abonnement_client.email
      INNER JOIN abonnement_historique as histo ON histo.id_sub = abonnement.id_sub
WHERE histo.id IN (
      SELECT subHisto.id FROM abonnement_historique AS subHisto
      GROUP BY subHisto.id_sub 
      ORDER BY subHisto.date_sub DESC
)

-- On trie à nouveau pour l'ordre d'affichage
ORDER BY histo.date_sub DESC;