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

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

  • Apparu en : SPIP 2.0

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

<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 <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+YXJ0aWNsZXM8L2NvZGU+"></span>
         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
</code>

-  Нарешті тег #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 <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+c3BpcF9kb2N1bWVudHNfbGllbnM8L2NvZGU+"></span>
         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.

Автор olly Publié le : Mis à jour : 27/04/23

Traductions : català, English, français, Nederlands, українська