Requête SQL: Jointure avec correspondance de 2 colonnes

Requête SQL: Jointure avec correspondance de 2 colonnes - SQL/NoSQL - Programmation

Marsh Posté le 20-06-2023 à 13:37:38    

Bonjour à tous,
 
J’ai une table « equipes » qui reprend à chaque fois 2 joueurs.
id_equipe   membre1   membre2
1     1             2
2        3             1
3     2             3
 
Et une table membres_liste
id_membre   nom   prenom
1           AAA     Anne
2           DDD     Pierre
3           BBB        Luc
 
Je cherche désespérément à afficher toutes les équipes avec le nom et prénom de chaque participant.
 
Ex :  
Equipe 1 :   Anne et Pierre
Equipe 2 :   Luc et Anne
Equipe 3 :   Pierre et Luc
 
Voici mon avancement:

Code :
  1. SELECT
  2. auteur_lead.nom as auteur_nom,
  3. auteur_lead.prenom as auteur_prenom,
  4. membre1,
  5. membre2,
  6. R.nom as B2B_nom,
  7. R.prenom as B2B_prenom
  8. FROM membres_liste auteur_lead
  9. RIGHT JOIN (
  10. SELECT membre1, membre2, nom, prenom
  11. FROM equipes
  12. INNER JOIN membres_liste ON membres_liste.id_membre = equipes.membre1
  13. WHERE date > '".$date_debut_en."' AND date <=  '".$date_fin_en."'
  14. UNION ALL
  15. SELECT membre2, membre1, nom, prenom
  16. FROM equipes
  17. INNER JOIN membres_liste ON membres_liste.id_membre = equipes.membre2
  18. WHERE date > '".$date_debut_en."' AND date <=  '".$date_fin_en."'
  19. ) R
  20. ON auteur_lead.id_membre = R.membre1
  21. ORDER BY auteur_lead.nom, auteur_lead.prenom ASC


 
J'ai mis R.membre1 dans ON, mais sans trop savoir quoi mettre d'autre...
Je sèche complètement...
 
Merci infiniment pour votre aide!

Reply

Marsh Posté le 20-06-2023 à 13:37:38   

Reply

Marsh Posté le 20-06-2023 à 14:06:45    

On va laisser de côté la structure de la table "equipes" qui me paraît pas être une bonne idée du tout puisque tu ne vas jamais pouvoir mettre plus de 2 membres et si tu as une équipe avec un seul membre, la colonne membre2 devra avoir la valeur NULL ce qui va compliquer certaines requêtes.
 
Pour ton truc, je verrais bien :

Code :
  1. SELECT e.id_equipe, m1.nom, m1.prenom, m2.nom, m2.prenom
  2. FROM equipes e LEFT JOIN membres_liste m1 ON (e.membre1 = m1.id_membre) LEFT JOIN membres_liste m2 ON (e.membre2 = m2.id_membre)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 20-06-2023 à 15:58:34    

Non non. Dans tous les cas, j’aurai toujours 2 personnes, ni plus ni moins. . J’ai parlé d’équipe pour que ce soit plus facile à comprendre.  
Je me penche sur ta proposition…

Reply

Marsh Posté le 20-06-2023 à 19:34:45    

rufo a écrit :

On va laisser de côté la structure de la table "equipes" qui me paraît pas être une bonne idée du tout puisque tu ne vas jamais pouvoir mettre plus de 2 membres et si tu as une équipe avec un seul membre, la colonne membre2 devra avoir la valeur NULL ce qui va compliquer certaines requêtes.
 
Pour ton truc, je verrais bien :

Code :
  1. SELECT e.id_equipe, m1.nom, m1.prenom, m2.nom, m2.prenom
  2. FROM equipes e LEFT JOIN membres_liste m1 ON (e.membre1 = m1.id_membre) LEFT JOIN membres_liste m2 ON (e.membre2 = m2.id_membre)



Sachant que ma table equipes n'aura toujours que 2 membres, y a pas moyen d'écrire ça autrement?
En réalité, mais requête est bien plus complexe car j'affiche également d'autres résultats d'autres tables. Le but étant d'afficher tous les résultats en même temps.
Le reste fonctionne correctement. Par rapport aux autres infos que je dois afficher, je suis parti sur un FROM membres_liste.
Tu n'aurais pas une idée pour écrire correctement la suite en partant de là? Mon UNION n'était pas une bonne idée?

Reply

Marsh Posté le 20-06-2023 à 21:42:02    

Sans avoir le MCD ou le MLD de ta BD ni quels résultats tu veux afficher exactement, ça va être compliqué.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 21-06-2023 à 07:40:16    

rufo a écrit :

Sans avoir le MCD ou le MLD de ta BD ni quels résultats tu veux afficher exactement, ça va être compliqué.


Rufo, tout d'abord, je voudrais te remercier car cela fait pas mal d'années que tu es tjs dispo pour aider et partager tes super connaissances. Je tenais à le souligner. Sincèrement merci!
 
Alors, je vais essayer d'être le plus clair possible. Je veux afficher toutes les réalisations des membres pour une période donnée (lead, CA et B2B).
Dans un premier temps, j'affiche tous les membres qui ont réaliser quelque chose. Jusque là, tout va bien.
Ensuite, (dans un accordion) j'affiche toutes les réalisations.
Pour les lead et CA, tout fonctionne. Mon souci est pour ajouter les éventuels B2B réalisés. (les B2B = les équipes dans ma demande initiale. J'avais changé les noms pour que ce soit plus clair).
Voici le code fonctionnel, sans la partie B2B:

Code :
  1. SELECT
  2. leads_liste.id_leads_liste,
  3. DATE_FORMAT(leads_liste.date,'%d-%m-%Y') as date_lead,
  4. leads_liste.auteur,
  5. leads_liste.membre,
  6. destinaire_lead.nom as destinataire_nom,
  7. destinaire_lead.prenom as destinataire_prenom,
  8. auteur_lead.nom as auteur_nom,
  9. auteur_lead.prenom as auteur_prenom,
  10. leads_liste.prospect,
  11. leads_liste.commentaire,
  12. leads_liste.statut,
  13. ca.id_ca,
  14. ca.montant,
  15. ca.commentaire as ca_commentaire,
  16. DATE_FORMAT(ca.date,'%d-%m-%Y') as date_ca
  17. FROM membres_liste auteur_lead
  18. lEFT JOIN leads_liste ON leads_liste.auteur = auteur_lead.id_membre
  19. LEFT JOIN ca ON ca.id_lead = leads_liste.id_leads_liste
  20. INNER JOIN membres_liste destinaire_lead ON destinaire_lead.id_membre = leads_liste.membre
  21. WHERE
  22. (leads_liste.date > '".$date_debut_en." 09:00:00' AND leads_liste.date <=  '".$date_fin_en."'
  23. OR
  24. ca.date > '".$date_debut_en." 09:00:00' AND ca.date <=  '".$date_fin_en."' )
  25. AND
  26. (leads_liste.auteur = ".$result['auteur']."
  27. OR
  28. leads_liste.membre = ".$result['auteur']." )
  29. ORDER BY leads_liste.date ASC


$result['auteur'] correspond au membre qui a réalisé qqch dans la requête précédente.
Histoire de compliquer encore un peu plus, il faut qu'une ligne s'affiche pour chaque membre qui ont réalisé un B2B. donc tant pour membre1 que pour membre2.
Voici mon ébauche, mais c'est pas encore correct.

Code :
  1. SELECT
  2. leads_liste.id_leads_liste,
  3. DATE_FORMAT(leads_liste.date,'%d-%m-%Y') as date_lead,
  4. leads_liste.auteur,
  5. leads_liste.membre,
  6. destinaire_lead.nom as destinataire_nom,
  7. destinaire_lead.prenom as destinataire_prenom,
  8. auteur_lead.nom as auteur_nom,
  9. auteur_lead.prenom as auteur_prenom,
  10. m2.nom as nom2,
  11. m2.prenom as prenom2,
  12. membre1,
  13. membre2,
  14. DATE_FORMAT(B2B_liste.date,'%d-%m-%Y') as date_B2B,
  15. leads_liste.prospect,
  16. leads_liste.commentaire,
  17. leads_liste.statut,
  18. ca.id_ca,
  19. ca.montant,
  20. ca.commentaire as ca_commentaire,
  21. DATE_FORMAT(ca.date,'%d-%m-%Y') as date_ca
  22. FROM membres_liste auteur_lead
  23. lEFT JOIN leads_liste ON leads_liste.auteur = auteur_lead.id_membre
  24. LEFT JOIN ca ON ca.id_lead = leads_liste.id_leads_liste
  25. INNER JOIN membres_liste destinaire_lead ON destinaire_lead.id_membre = leads_liste.membre
  26. LEFT JOIN B2B_liste ON (B2B_liste.membre1 = auteur_lead.id_membre)
  27. LEFT JOIN membres_liste m2 ON (B2B_liste.membre2 = m2.id_membre)
  28. WHERE
  29. (leads_liste.date > '".$date_debut_en." 09:00:00' AND leads_liste.date <=  '".$date_fin_en."'
  30. OR
  31. ca.date > '".$date_debut_en." 09:00:00' AND ca.date <=  '".$date_fin_en."' )
  32. AND
  33. (leads_liste.auteur = ".$result['auteur']."
  34. OR
  35. leads_liste.membre = ".$result['auteur']."
  36. OR
  37. B2B_liste.membre1 = ".$result['auteur']."
  38. OR
  39. B2B_liste.membre2 = ".$result['auteur']."
  40. )
  41. ORDER BY leads_liste.date ASC


Message édité par bingojm le 21-06-2023 à 07:40:51
Reply

Marsh Posté le 21-06-2023 à 08:06:33    

Tu sais que tu peux faire plus requêtes SQL et laisser ensuite le code de ton appli (du PHP ?) prendre les données récupérées et les mettre aux bon endroits dans l'IHM. Parce que j'ai l'impression que tu essayes de faire beaucoup de choses dans une même requête complexe alors que tu pourrais le faire plus facilement dans x requêtes.
 
Ca serait beaucoup plus simple si tu donnais ton MCD (modèle conceptuel de données = représentation graphique des tables et des relations entre elles) ou ton MLD (modèle logique de données = tables et champs tels qu'implémentés dans ton SGBD) avec un exemple concret de ce que tu veux obtenir (quelques lignes de données dans tes tables et le résultat que tu veux avoir en sortie correspondant à ces données). C'est sans doute très clair dans ta tête, mais pour ma part, n'étant pas dans ton projet, j'ai du mal à voir précisément ce que tu veux.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 26-06-2023 à 11:39:07    

Tu peux aussi t'en sortir avec une sous requête dans le SELECT si tu veux éviter les left join. C'est moins élégant, pas performant mais ça peut aider.
C'est un peu la même chose qu'utiliser des fonctions.
 

Code :
  1. SELECT id, CONCAT(SELECT prenom FROM membres_liste WHERE id_membre = equipes.membre1), " et " (SELECT prenom FROM membres_liste WHERE id_membre = equipes.membre2)) as composition
  2. FROM equipes


 
Après c'est déguelasse mais ça peut dépanner

Reply

Marsh Posté le 27-06-2023 à 22:00:14    

Ok, je vais essayer d'éviter pour avoir qqch de propre, du moins le plus possible.
 
Suite aux conseils de Rufo, je suis parti sur plusieurs requêtes. Le résultat me convient, mais au départ je voulais classer tout par date. Du coup, en php, c'est aussi réalisable de rassembler les résultats des différentes requêtes et de les classer par date???
 
Par contre, il me reste encore une requête importante qui me pose problème. Je veux simplement afficher le nom des personnes qui ont réalisé quelque chose sur une période donnée.
Donc afficher le nom de personnes (de membres_liste) présentes dans: leads_liste ET/OU B2B_liste (soit dans la colonne membre1 ou membre2) ET/OU ca.
Le problème est que mon code n'affiche que les noms s'ils sont au moins présents dans leads_liste et pas s'ils sont seulement dans B2B_liste ou dans ca alors que je voudrais que les noms soient affichés (une seule fois) s'ils sont présents au moins une fois dans n'importe laquelle de ces 3 tables...

Code :
  1. SELECT
  2.            leads_liste.auteur,
  3.            membres_liste.nom as auteur_nom,
  4.            membres_liste.prenom as auteur_prenom
  5.           FROM membres_liste
  6.           LEFT JOIN leads_liste ON leads_liste.auteur = membres_liste.id_membre
  7.           LEFT JOIN ca ON ca.id_lead = leads_liste.id_leads_liste
  8.           LEFT JOIN B2B_liste ON (B2B_liste.membre1 = membres_liste.id_membre
  9.           OR B2B_liste.membre2 = membres_liste.id_membre)
  10.           AND B2B_liste.date > '".$date_debut_en." 09:00:00' AND B2B_liste.date <=  '".$date_fin_en."'
  11.           WHERE leads_liste.date > '".$date_debut_en." 09:00:00' AND leads_liste.date <=  '".$date_fin_en."'
  12.           GROUP BY membres_liste.id_membre
  13.           ORDER BY membres_liste.nom, membres_liste.prenom ASC


Reply

Marsh Posté le 27-06-2023 à 22:57:45    

Pour le tri par date, tu peux stocker les résultats de chaque requête dans un seul tableau associatif dont les clés sont les dates au format yyy-mm-aa. A chaque clé est associé un tableau associatif qui contient les enregistrements (les clés sont les noms des colonnes du SELECT).
Après, tu utilises la fonction ksort() sur le tableau pour trier par date croissante.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 27-06-2023 à 22:57:45   

Reply

Marsh Posté le 28-06-2023 à 06:20:39    

Super merci. Je vais me documenter là-dessus!
 
Il reste à trouver une solution pour ma dernière requête qui me pose problème… une idée?

Reply

Marsh Posté le 28-06-2023 à 08:07:47    

Pourquoi tu as mis leads_liste.date > '".$date_debut_en." 09:00:00' AND leads_liste.date <=  '".$date_fin_en."' dans le WHERE et pas dans le "ON" de la jointure de ton LEFT JOIN comme t'as fait pour B2B ?
Je pense que ton pb vient de là.

Message cité 1 fois
Message édité par rufo le 28-06-2023 à 08:08:09

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 28-06-2023 à 08:22:15    

rufo a écrit :

Pourquoi tu as mis leads_liste.date > '".$date_debut_en." 09:00:00' AND leads_liste.date <=  '".$date_fin_en."' dans le WHERE et pas dans le "ON" de la jointure de ton LEFT JOIN comme t'as fait pour B2B ?
Je pense que ton pb vient de là.


Effectivement, ça n'est pas correct.
Voici la correction, mais il y a un souci. Il me manque beaucoup d'enregistrements et le reste de la page ne s'affiche pas. Bug qq part.

Code :
  1. SELECT
  2.            leads_liste.auteur,
  3.            membres_liste.nom as auteur_nom,
  4.            membres_liste.prenom as auteur_prenom
  5.           FROM membres_liste
  6.           LEFT JOIN leads_liste ON leads_liste.auteur = membres_liste.id_membre
  7.           AND leads_liste.date > '".$date_debut_en." 09:00:00' AND leads_liste.date <=  '".$date_fin_en."'
  8.           LEFT JOIN ca ON ca.id_lead = leads_liste.id_leads_liste
  9.           LEFT JOIN B2B_liste ON (B2B_liste.membre1 = membres_liste.id_membre
  10.           OR B2B_liste.membre2 = membres_liste.id_membre)
  11.           AND B2B_liste.date > '".$date_debut_en." 09:00:00' AND B2B_liste.date <=  '".$date_fin_en."'
  12.           GROUP BY membres_liste.id_membre
  13.           ORDER BY membres_liste.nom, membres_liste.prenom ASC

Reply

Marsh Posté le 28-06-2023 à 08:54:43    

Sais tu qu'en faisant des LEFT JOIN il essaye de récupérer des valeurs dans leads_liste correspondant à ton ON mais que si il n'y arrive pas tu as quand même une ligne "membres" ?
 
Sais tu qu'en faisant un GROUP BY membres_liste.id_membre ça va écraser les multiples jointure possible dans leads_liste pour n'en garder qu'une ?
 
Si tu est partis pour faire un traitement en PHP, tu devrais te simplifier la vie et faire moins de chose en SQL et plus en PHP, par exemple récupérer tout tes auteurs (id, nom, prenom) que tu met dans un array[id] = array(nom, prenom) et qu'ensuite tu as sous le coude pour ton affichage de ca / lead ou b2b...


---------------
D3
Reply

Marsh Posté le 28-06-2023 à 09:44:42    

mechkurt a écrit :

Sais tu qu'en faisant des LEFT JOIN il essaye de récupérer des valeurs dans leads_liste correspondant à ton ON mais que si il n'y arrive pas tu as quand même une ligne "membres" ?
 
Sais tu qu'en faisant un GROUP BY membres_liste.id_membre ça va écraser les multiples jointure possible dans leads_liste pour n'en garder qu'une ?
 
Si tu est partis pour faire un traitement en PHP, tu devrais te simplifier la vie et faire moins de chose en SQL et plus en PHP, par exemple récupérer tout tes auteurs (id, nom, prenom) que tu met dans un array[id] = array(nom, prenom) et qu'ensuite tu as sous le coude pour ton affichage de ca / lead ou b2b...


Effectivement, tu relèves déjà un souci que je n'arrive pas à expliquer: avec des left join, je suis censé avoir toutes la liste des membres, même s'ils n'ont rien réalisé, mais ce n'est pas le cas... Je n'arrive pas à dire pourquoi.
 
Pour le GROUP BY, c'est bien correct! je ne veux afficher qu'une seule fois le nom du membre, pour autant qu'il ait réalisé qqch dans leads_liste ET/OU B2B_liste (soit dans la colonne membre1 ou membre2) ET/OU ca.
 
Vaut mieux que je parte sur plusieurs requêtes alors? Si oui, comment n'afficher qu'une seule fois le nom du membre en php s'il apparait dans plusieurs tables?
 
Merci encore!

Reply

Marsh Posté le 28-06-2023 à 11:09:44    

Avec du PHP si tu fais plusieurs requêtes. Tu fais ta première requête, tu stockes le résultat dans un tableau associatif dont la clé sera l'ID du membre. Ainsi, lors de la 2ème requête, tu n'ajouteras chaque enregistrement dans le tableau que si if (!isset($MonTableau[$IDMembre])) ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 28-06-2023 à 20:04:24    

C'est pas ça qu'il te faut ?
Ca marche au top chez moi :  
SELECT  
     equipes.id,
     mb1.prenom,
     mb2.prenom  
    FROM  
     equipes
   LEFT JOIN membres_liste mb1 ON equipes.membre1 = mb1.id
   LEFT JOIN membres_liste mb2 ON equipes.membre2 = mb2.id


---------------
Pays et country_code traduits : https://www.iso-country-code.com
Reply

Marsh Posté le 28-06-2023 à 20:20:43    

ragondin a écrit :

C'est pas ça qu'il te faut ?
Ca marche au top chez moi :  
SELECT  
     equipes.id,
     mb1.prenom,
     mb2.prenom  
    FROM  
     equipes
   LEFT JOIN membres_liste mb1 ON equipes.membre1 = mb1.id
   LEFT JOIN membres_liste mb2 ON equipes.membre2 = mb2.id


Ça pourrait mais comment faire si je veux voir si un membre est aussi inscrit dans une autre table que equipes ?
Je cherche à afficher une seule fois son nom si il est inscrit dans au moins une des deux tables.

Reply

Marsh Posté le 28-06-2023 à 20:59:55    

Je comprends mais ta demande était "Je cherche désespérément à afficher toutes les équipes avec le nom et prénom de chaque participant."
 
Là, ma requete affiche toutes les equipes (FROM equipes) avec le nom et prénom de chaque participant (bon il manque le nom mais le + dur était fait).
 
Tu rajoutes des conditions par rapport à ta demande initiale.


---------------
Pays et country_code traduits : https://www.iso-country-code.com
Reply

Marsh Posté le 28-06-2023 à 22:27:34    

rufo a écrit :

Avec du PHP si tu fais plusieurs requêtes. Tu fais ta première requête, tu stockes le résultat dans un tableau associatif dont la clé sera l'ID du membre. Ainsi, lors de la 2ème requête, tu n'ajouteras chaque enregistrement dans le tableau que si if (!isset($MonTableau[$IDMembre])) ;)


Merci rufo! En suivant cette méthode, j'arrive à afficher les id_membre qu'il me faut! Merci infiniment!
Pour afficher les noms et les prénoms de ces membres, je suppose qu'il faut que je refasse une nouvelle requête? Je me permets de poser la question pour maîtriser correctement enfin ce problème sans faire une requête supplémentaire qui pourrait être évitée!

Reply

Marsh Posté le 29-06-2023 à 07:44:58    

Mais non, pas de nouvelle requête. Ton tableau est associatif. Ca veut dire qu'il est de la forme :
array(
         5 => array('Nom' => 'xx', 'Prénom' => 'yyyy'),
         3 => array('Nom' => 'zzzz', 'Prénom' => 'ttttt'),
         7 => array('Nom' => 'aaaa', 'Prénom' => 'bbbb'),
         ...
       )
 
Les clés sont les ID des membres.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 29-06-2023 à 08:37:46    

Code :
  1. $results = $pdo->query(" SELECT id, prenom, nom FROM membres_liste  WHERE 1 " );
  2. $members = array();
  3. while($row = $result->fetch(PDO::FETCH_ASSOC)) {
  4.     $members[$row['id']] = $row['nom'].' '.$row['prenom'];
  5. }
  6. var_dump($members);


Et après quand tu vas chercher tes enregistrements par date tu n'as plus besoin de faire de jointure avec la table membres, pour les afficher tu peux faire:

Code :
  1. $results = $pdo->query(" SELECT date, auteur FROM leads_liste WHERE date > '".$date_debut_en." 09:00:00' AND date <=  '".$date_fin_en."' " );
  2. $output = "<pre>";
  3. while($row = $result->fetch(PDO::FETCH_ASSOC)) {
  4.     $output .= "\n".$row['date'].' => '.$members[$row['auteur ']];
  5. }

Message cité 1 fois
Message édité par mechkurt le 29-06-2023 à 08:38:01

---------------
D3
Reply

Marsh Posté le 29-06-2023 à 10:09:53    

Un immense merci à tous!
J'y suis arriver, et surtout, j'ai appris plein de choses!
 
Dernière petite question: est-ce que par hasard, il y a moyen d'afficher les résultats du tableau de manière totalement aléatoire pour éviter d'avoir l'ordre dans lequel ils ont été enregistrés?

Reply

Marsh Posté le 29-06-2023 à 10:37:22    

Tu fais un ORDER BY RAND() dans ta requête SQL.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 05-07-2023 à 15:44:01    

Me revoilà avec une nouvelle question car j'ai du mal avec les tableaux php.
 
En suivant vos conseils de passer les valeurs dans un tableau, j'essaie d'y mettre les id, nom, prenom... dans un tableau multidimensionnel.
Je lis bcp de documentation, mais j'ai du mal à y arriver. Merci de votre indulgence...
 
Voici l'idée:

Code :
  1. $req13 = mysqli_query($base, "SELECT
  2.             membres_liste.id_membre,
  3.             membres_liste.nom,
  4.             membres_liste.prenom,
  5.             COUNT(a.id_B2B_liste) as nb_B2B_a
  6.             FROM membres_liste
  7.            INNER JOIN B2B_liste a ON a.membre1 = membres_liste.id_membre
  8.            AND a.date > '".$date_debut_en." 09:00:00' AND a.date <=  '".$date_fin_en."'
  9.            WHERE membres_liste.statut = 1
  10.            GROUP BY membres_liste.id_membre
  11.            " ) or die('Erreur SQL : '.mysqli_error($base));   
  12.       //On regarde s'il y a des enregistrements qui répondent aux critères
  13.       $nb = mysqli_num_rows($req13);
  14.       if($nb > 0 )
  15.       {
  16.        //Si oui...
  17.        $tableau_B2B = array();
  18.        while ($result13 = mysqli_fetch_array($req13)) {
  19.         //On ajoute dans le tableau les membres   
  20.         if (!isset($tableau_B2B[$result13['id_membre']]))
  21.         {
  22.          $tableau_B2B = [
  23.           [ 'id' => $result13['id_membre'],
  24.             'nom' => $result13['nom'],
  25.             'prenom' => $result13['prenom'],
  26.             'count' => $result13['nb_B2B_a']
  27.           ]
  28.          ];
  29.         }
  30.        }
  31.       }
  32.       var_dump($tableau_B2B);


Déjà là, j'ai un problème car il n'enregistre qu'une seule valeur et pas toutes.
 
Ensuite, l'idée était de faire la même requête en sélectionnant le nom de la 2ème colonne: INNER JOIN B2B_liste a ON a.membre2 = membres_liste.id_membre
après quoi j'aurais comparé si l'enregistrement était déjà dans le tableau. Là aussi, je bloque.
Car si la valeur n'y pas, je l'ajoute.
Mais si elle y est, je veux ajouter la valeur de nb_B2B_b à la la valeur de nb_B2B_a.
 
Je désespère...
Merci de bien vouloir me montrer un exemple correct d'écriture svp

Reply

Marsh Posté le 05-07-2023 à 16:08:36    


bingojm a écrit :

Me revoilà avec une nouvelle question car j'ai du mal avec les tableaux php.
 
En suivant vos conseils de passer les valeurs dans un tableau, j'essaie d'y mettre les id, nom, prenom... dans un tableau multidimensionnel.
Je lis bcp de documentation, mais j'ai du mal à y arriver. Merci de votre indulgence...
 
Voici l'idée:

Code :
  1. $req13 = mysqli_query($base, "SELECT
  2.             membres_liste.id_membre,
  3.             membres_liste.nom,
  4.             membres_liste.prenom,
  5.             COUNT(a.id_B2B_liste) as nb_B2B_a
  6.             FROM membres_liste
  7.            INNER JOIN B2B_liste a ON a.membre1 = membres_liste.id_membre
  8.            AND a.date > '".$date_debut_en." 09:00:00' AND a.date <=  '".$date_fin_en."'
  9.            WHERE membres_liste.statut = 1
  10.            GROUP BY membres_liste.id_membre
  11.            " ) or die('Erreur SQL : '.mysqli_error($base));   
  12.       //On regarde s'il y a des enregistrements qui répondent aux critères
  13.       $nb = mysqli_num_rows($req13);
  14.       if($nb > 0 )
  15.       {
  16.        //Si oui...
  17.        $tableau_B2B = array();
  18.        while ($result13 = mysqli_fetch_array($req13)) {
  19.         //On ajoute dans le tableau les membres   
  20.         if (!isset($tableau_B2B[$result13['id_membre']]))
  21.         {
  22.          $tableau_B2B = [
  23.           [ 'id' => $result13['id_membre'],
  24.             'nom' => $result13['nom'],
  25.             'prenom' => $result13['prenom'],
  26.             'count' => $result13['nb_B2B_a']
  27.           ]
  28.          ];
  29.         }
  30.        }
  31.       }
  32.       var_dump($tableau_B2B);


Déjà là, j'ai un problème car il n'enregistre qu'une seule valeur et pas toutes.
 
Ensuite, l'idée était de faire la même requête en sélectionnant le nom de la 2ème colonne: INNER JOIN B2B_liste a ON a.membre2 = membres_liste.id_membre
après quoi j'aurais comparé si l'enregistrement était déjà dans le tableau. Là aussi, je bloque.
Car si la valeur n'y pas, je l'ajoute.
Mais si elle y est, je veux ajouter la valeur de nb_B2B_b à la la valeur de nb_B2B_a.
 
Je désespère...
Merci de bien vouloir me montrer un exemple correct d'écriture svp


Le problème avec ton code c'est que tu n'indice pas ton tableau avec l'id du membre (j'ai même l'impression que tu re-crées un nouveau tableau avec une seule entité à chaque boucle de ton while).
Ce n'est pas comme si j'avais pas donné un code fonctionnel un peu plus haut...

mechkurt a écrit :

Code :
  1. $results = $pdo->query(" SELECT id, prenom, nom FROM membres_liste  WHERE 1 " );
  2. $members = array();
  3. while($row = $result->fetch(PDO::FETCH_ASSOC)) {
  4.     $members[$row['id']] = $row['nom'].' '.$row['prenom'];
  5. }
  6. var_dump($members);


Et après quand tu vas chercher tes enregistrements par date tu n'as plus besoin de faire de jointure avec la table membres, pour les afficher tu peux faire:

Code :
  1. $results = $pdo->query(" SELECT date, auteur FROM leads_liste WHERE date > '".$date_debut_en." 09:00:00' AND date <=  '".$date_fin_en."' " );
  2. $output = "<pre>";
  3. while($row = $result->fetch(PDO::FETCH_ASSOC)) {
  4.     $output .= "\n".$row['date'].' => '.$members[$row['auteur ']];
  5. }




---------------
D3
Reply

Marsh Posté le 05-07-2023 à 16:14:48    

mechkurt a écrit :


Le problème avec ton code c'est que tu n'indice pas ton tableau avec l'id du membre (j'ai même l'impression que tu re-crées un nouveau tableau avec une seule entité à chaque boucle de ton while).
Ce n'est pas comme si j'avais pas donné un code fonctionnel un peu plus haut...


Oui, ok pour la clé du tableau, mais ici je ne veux pas simplement afficher le nom (ce n'est plus la même requête qu'au départ). Il me faut le nom, prenom et le count.
C'est pour ça que je cherchais à m'orienter vers un tableau multidimensionnel (en pensant que c'est la meilleure solution).

Reply

Marsh Posté le 05-07-2023 à 17:56:58    

Code :
  1. $members = array();
  2. while ($row = mysqli_fetch_assoc($req13)) {
  3.     $members[$row['id_membre']] = array(
  4.         'nom' => $row['nom'],
  5.         'prenom' => $row['prenom'],
  6.         'count' => $row['nb_B2B_a']
  7.     );
  8. }


---------------
D3
Reply

Marsh Posté le 06-07-2023 à 12:04:59    

mechkurt a écrit :

Code :
  1. $members = array();
  2. while ($row = mysqli_fetch_assoc($req13)) {
  3.     $members[$row['id_membre']] = array(
  4.         'nom' => $row['nom'],
  5.         'prenom' => $row['prenom'],
  6.         'count' => $row['nb_B2B_a']
  7.     );
  8. }



Merci beaucoup! Avec tous mes essais, je n'étais pas loin, mais j'y arrive grâce à toi!
 
Je me demandais encore une chose: comment trier les résultats par ordre décroissant, mais sur base de $count?
J'ai bien vu la fonction arsort(), mais je ne vois pas quoi mettre dedans et à quel endroit, étant donné que ce n'est pas sur base de la clé que je veux classer...  
Du coup, comment sélectionner la valeur que je veux classer étant donné qu'il y en a plusieurs?


Message édité par bingojm le 06-07-2023 à 15:11:13
Reply

Marsh Posté le 06-07-2023 à 16:33:35    

Ne serait il pas plus simple de trier tes résultats au niveau de ta requête SQL avec un ORDER BY ?

Code :
  1. SELECT
  2.     membres_liste.id_membre,
  3.     membres_liste.nom,
  4.     membres_liste.prenom,
  5.     COUNT(a.id_B2B_liste) as nb_B2B_a
  6. FROM membres_liste
  7. INNER JOIN B2B_liste a ON a.membre1 = membres_liste.id_membre
  8.                               AND a.date > '".$date_debut_en." 09:00:00' AND a.date <=  '".$date_fin_en."'
  9. WHERE membres_liste.statut = 1
  10. GROUP BY membres_liste.id_membre
  11. ORDER BY COUNT(a.id_B2B_liste) DESC


Les bases de données c'est un peu fait pour ça...  [:nedurb]
 
Ton tableau associatif id_membre => tableau d'info membre ne sera pas trié par id_membre mais bien dans l'ordre ou tu l'as remplis.


---------------
D3
Reply

Marsh Posté le 06-07-2023 à 17:38:31    

Ah c'est sûr que ça serait plus simple! Mais cfr toute la discussion plus haut, on m'a conseillé de faire deux tables différentes et ajouter les données dans un tableau.
La deuxième requête est exactement la même, sauf la ligne è : INNER JOIN B2B_liste a ON a.membre2 = membres_liste.id_membre.
Le but étant de savoir combien de fois les membres étaient enregistrés, tant dans la colonne membre1 que dans la colonne membre2.
 
Donc ça au final, j'y suis bien arrivé.
 
Effectivement,  il est trié par ordre où je l'ai rempli. Mais y a-t-il moyen de changer cet ordre sur base d'une des valeurs, à savoir la valeur COUNT uniquement?
Est-ce possible d'utiliser arsort(), mais en ciblant directement la valeur de COUNT?

Reply

Marsh Posté le 06-07-2023 à 18:19:18    

Ca serait plutôt la fonction uasort() qu'il faut utiliser ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 06-07-2023 à 18:44:07    

rufo a écrit :

Ca serait plutôt la fonction uasort() qu'il faut utiliser ;)


Merci rufo!
En testant ces fonctions, ce que je n'arrive surtout pas à faire depuis tout à l'heure, c'est ciblé la fonction sur la valeur du count.
J'essaie par exemple ceci, mais ce n'est pas correct:

Code :
  1. foreach ($members as $cle_1 => $valeur_1)
  2.       {
  3.         //On trie les résultats par ordre décroissant
  4.         function trier($a, $b)
  5.         {
  6.        if ($a == $b) return 0;
  7.          return ($a > $b) ? -1 : 1;
  8.         }
  9.         uasort($members[$cle_1]['count'], "trier" );
  10.        $body  = "<tr>";
  11.        $body .= "<td align='center'>".(++$num_ligne)."</td>";
  12.        $body .= "<td>".$members[$cle_1]['nom']." ".$members[$cle_1]['prenom']."</td>";
  13.        $body .= "<td align='center'>".$members[$cle_1]['count']."</td>";
  14.        $body .= "</tr>";
  15.        echo $body;
  16.       }


Je dois mettre la fonction trier dans le foreach?
Et c'est surtout la ligne 9 qui me pose problème pour tester davantage :(

Reply

Marsh Posté le 06-07-2023 à 19:14:06    

Non, faut créer une fonction callback qui prend en paramètre 2 valeurs à comparer et la fonction renvoie 0, 1, -1 suivant que la valeur $a est =, >, < à la valeur $b.
uasort() jouera le rôle de la boucle foreach sur ton tableau à trier.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed