SPIP

[ar] [ast] [bg] [br] [ca] [co] [cpf] [cs] [da] [de] [en] [eo] [es] [eu] [fa] [fon] [fr] [gl] [id] [it] [ja] [lb] [nl] [oc] [pl] [pt] [ro] [ru] [sk] [sv] [tr] [vi] [zh] Espace de traduction

Télécharger

Les jointures entre tables

Juillet 2010 — mis à jour le : Août 2010

Toutes les versions de cet article :

exemples de boucles produisant une jointure multiple entre 3 tables
[spip 2.0.9]


nous voulons, en une boucle, récupérer les informations des articles d’une (ou plusieures) rubrique à laquelle est affecté un mot clef (que nous connaissons).

<BOUCLE_a(ARTICLES spip_mots_rubriques spip_mots) {titre_mot=truc}>

produira la requête sql suivante :

 SELECT articles.id_rubrique,
        articles.id_article,
        ...
        articles.lang
   FROM spip_articles AS `articles`
        INNER JOIN spip_mots_rubriques AS L1
                ON L1.id_rubrique = articles.id_rubrique
        INNER JOIN spip_mots AS L2
                ON L2.id_mot = L1.id_mot
  WHERE articles.statut = 'publie'
    AND L2.titre = 'truc'
GROUP BY articles.id_article

nous voulons en une boucle sélectionner aléatoirement un document dans un secteur. À savoir que ce secteur ne contient pas d’articles, seulement des rubriques avec des documents liés (photothèque).

<BOUCLE_d(spip_documents_liens rubriques)
         {objet = rubrique}
         {rubriques.id_secteur = 13}
         {par hasard}
         {0, 1}>
 #LOGO_DOCUMENT
</BOUCLE_d>

-  la table spip_documents_liens est une table qui recense les liens (jointures) entre un document et un objet (article, rubrique, mot, site...).

des entrées type de cette table pourraient ressembler à :

id_document id_objet objet vu
14 36 article non
363 66 rubrique non
... ... ... ...

nous allons donc chercher dans cette table les documents rattachés à une rubrique {objet = rubrique}

mais nous voulons aussi que cette rubrique soit descendante de la rubrique secteur d’id 13

nous devons donc établir dans notre requête une jointure entre la table spip_documents_liens et spip_rubriques

cette jointure sera faite sur d’un côté :
l’id_objet de spip_documents_liens, de l’autre
l’id_rubrique de spip_rubriques

pour cela nous indiquons à spip que nous voulons cette jointure spécifique en donnant les 2 tables à la boucle <BOUCLE_d(spip_documents_liens rubriques)...

enfin, pour spécifier notre restriction concernant le secteur 13, nous précisons le critère {rubriques.id_secteur = 13} en spécifiant explicitement le nom complet du champ (nom de la table inclu) pour que la requête n’aille pas chercher un champ spip_documents_liens.id_secteur qui n’existe pas.

-  à partir de cette boucle, donc, nous avons alors accès à tous les champs de spip_documents_liens et tous ceux de spip_rubriques :

#ID_DOCUMENT
#ID_OBJET
#OBJET
#VU

#ID_RUBRIQUE
#ID_PARENT
#TITRE
#DESCRIPTIF
#TEXTE
#ID_SECTEUR
...

-  la requête sql produite par notre boucle :

 SELECT rand() AS alea,
        spip_documents_liens.id_document
   FROM spip_documents_liens AS `spip_documents_liens`
        INNER JOIN spip_rubriques AS L1
                ON L1.id_rubrique = spip_documents_liens.id_objet
               AND spip_documents_liens.objet = 'rubrique'
  WHERE spip_documents_liens.objet = 'rubrique'
    AND L1.id_secteur = 13
GROUP BY spip_documents_liens.id_document,
        spip_documents_liens.id_objet,
        spip_documents_liens.objet
ORDER BY alea
  LIMIT 0,1

-  enfin, la balise #LOGO_DOCUMENT nous retournera le source html :

<img src='local/cache-vignettes/L135xH150/Image_10-d84e2.png'
width='135' height='150' style='height:150px;width:135px;' alt=''
class='spip_logos' />

et si nous voulions le nom du fichier document, que nous ne pouvons avoir directement avec cette requête car le champ spip_documents.fichier n’est pas relevé (pas de jointure avec la table spip_documents), alors il faut déclarer une jointure supplémentaire sur la table spip_documents :

<BOUCLE_d(spip_documents_liens documents rubriques)
         {objet = rubrique}
         {rubriques.id_secteur = 13}
         {par hasard}
         {0, 1}>
#LOGO_DOCUMENT / #FICHIER
</BOUCLE_d>

requête produite :

 SELECT rand() AS alea,
        spip_documents_liens.id_document,
        L2.fichier
   FROM spip_documents_liens AS `spip_documents_liens`
        INNER JOIN spip_documents AS L2
                ON L2.id_document = spip_documents_liens.id_document
        INNER JOIN spip_rubriques AS L1
                ON L1.id_rubrique = spip_documents_liens.id_objet
               AND spip_documents_liens.objet='rubrique'
  WHERE spip_documents_liens.objet = 'rubrique'
    AND L1.id_secteur = 13
GROUP BY spip_documents_liens.id_document,
        spip_documents_liens.id_objet,
        spip_documents_liens.objet
ORDER BY alea
  LIMIT 0,1

attention n° 1 :
-  ici, nous avons presque accès à tous les champs des 3 tables
« presque » car attention aux champs homonymes :
les #TITRE, #DESCRIPTIF, #MAJ, #STATUT et #DATE affichés, qui sont des champs homonymes dans spip_documents et spip_rubriques, seront ceux de spip_documents (table première de la requête) !

attention n° 2 :
-  les écritures de nom de table

si :

 <BOUCLE_d(DOCUMENTS_LIENS
 <BOUCLE_d(documents_liens
  <BOUCLE_d(SPIP_DOCUMENTS_LIENS
  <BOUCLE_d(spip_documents_liens

sont équivalentes ;

tout comme :

 <BOUCLE_d(documents_liens documents rubriques
 <BOUCLE_d(documents_liens documents spip_rubriques
 <BOUCLE_d(documents_liens documents RUBRIQUES

sont équivalentes ;

et encore :

 <BOUCLE_d(documents_liens documents
 <BOUCLE_d(documents_liens spip_documents
 <BOUCLE_d(spip_documents_liens spip_documents
 <BOUCLE_d(spip_documents_liens documents

sont aussi équivalentes ;

il n’en va pas de même avec :

 <BOUCLE_d(DOCUMENTS_LIENS DOCUMENTS
 <BOUCLE_d(documents_liens DOCUMENTS
 <BOUCLE_d(SPIP_DOCUMENTS_LIENS DOCUMENTS
 <BOUCLE_d(spip_documents_liens DOCUMENTS

où la mise en capitales de documents occasionne une perte de jointure entre spip_documents_liens et spip_documents


Voir le squelette de cette page Site réalisé avec SPIP | Espace de traduction | Espace privé