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] [uk] [vi] [zh] Espace de traduction

Télécharger

Поєднання таблиць

Juillet 2015 — mis à jour le : Novembre 2015

Toutes les versions de cet article :

Деякі приклади циклів, які генерують декілька поєднань між 3-ма таблицями
[spip 2.0.9]


Ми хочемо в одному циклі витягти дані щодо деяких статей з однієї (або кількох) рубрик, до яких були заздалегідь призначені ключі.

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

буде генерувати наступний SQL запит:

 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 = 'search_keyword'
GROUP BY articles.id_article

Ми хочемо в одному циклі випадковим чином вибрати документ з сектора. Зверніть увагу, що цей сектор не містить будь-яких власних статей, а тільки рубрики і пов’язані з ними документи (насправді це - фото-бібліотека).

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

-  Таблиця spip_documents_liens - це таблиця, яка зіставляє всі посилання (об’єднання) між документом і об’єктами (статтями, рубриками, ключами, сайтами і т.д.)

Деякі типові записи в цій таблиці будуть виглядати так:

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

Отже ми, таким чином, будемо шукати в цій таблиці документи, пов’язані з рубрикою {objet = rubrique}

Ми також будемо вважати, що ця рубрика вкладена в сектор з ID = 13.

Тому ми повинні встановити в нашому запиті, що об’єднання (join) зроблено між таблицями spip_documents_liens і spip_rubriques .

Це об’єднання встановлюється між:
id_objet в spip_documents_liens, і
id_rubrique в spip_rubriques.

Щоб зробити об’єднання, ми розповімо SPIP, що ми хочемо виконати це конкретне об’єднання, вказавши 2 таблиці всередині синтаксису циклу <BOUCLE_d(spip_documents_liens rubriques)...

Нарешті, щоб вказати наш обмеження щодо сектора 13, ми використовуємо критерій {rubriques.id_secteur = 13}, явно прописуючи детальне повне ім’я поля (в тому числі - ім’я таблиці), аби запит не спробував знайти поле spip_documents_liens.id_secteur, якого насправді не існує.

-  Використовуючи цей цикл ми отримуємо доступ до всіх полів в таблиці spip_documents_liens і всіх полів в spip_rubriques:

#ID_DOCUMENT
#ID_OBJET
#OBJET
#VU

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

-  Поки що наш згенерований SQL запит для нашого циклу виглядає так:

 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

-  Нарешті тег #LOGO_DOCUMENT поверне нам HTML-джерело для документу:

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

Тепер, якщо ми також хочемо одержати ім’я файла документа, оскільки ми не можемо отримати доступ до нього за цим запитом, бо поле spip_documents.fichier не було включене (без з’єднання з таблицею spip_documents), то ми повинні оголосити додаткове об’єднання з таблицею spip_documents:

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

Запит SQL тоді буде таким:

 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

Важливе зауваження № 1:
-  за цим сценарієм, ми маємо доступ майже до всіх полів в 3-х таблицях
«майже», бо деякі поля мають однакові імена:
поля #TITRE, #DESCRIPTIF, #MAJ, #STATUT і #DATE, що відображатимуться, мають відповідні поля з такими ж іменами в обох таблицях: spip_documents і spip_rubriques, а відображаєтися будуть значення з таблиці spip_documents (першої таблиці в запиті)!

Важливе зауваження № 2:
-  синтаксис для запису імен таблиць.

Хоча:

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

всі еквівалентні;

як і цикли:

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

будуть еквівалентні один одному;

і навіть в цьому наборі:

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

цикли також еквівалентні між собою;

ми не можемо сказати те ж саме про цій набір:

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

де запис documents великими літерами викличе втрату автоматичного об’єднання між spip_documents_liens і spip_documents.


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