MySQL - Dva cizí klíče ukazující na stejnou tabulku

Ukázání dvou cizích klíčů na jednu tabulku je hraniční případ. Pokud je to možné, je lepší upravit strukturu databáze. V opačném případě budete muset upravit kód seznamu READ.


O konstrukcích se dvěma spoji k jednomu stolu

Použití dvou spojení do stejné tabulky je v některých případech zcela logická struktura, ale tento typ struktury je často nepraktický.

Uveďme si jednoduchý příklad:

MySQL two joins to the same table example
Příklad tabulky MySQL se dvěma spojeními do stejné tabulky

Pro výběr záznamů z tabulky projektů je třeba použít tento druh dotazu:

SELECT
    projects.name,
    manager.name AS manager_name,
    manager.firstname AS manager_firstname,
    employee.name AS employee_name,
    employee.firstname AS employee_firstname
FROM
    projects
    LEFT JOIN persons AS manager ON projects.manager_id = manager.id
    LEFT JOIN persons AS employee ON projects.employee_id = employee.id

Tento dotaz používá aliasy pro pole tabulky osob, ale také pro název samotné tabulky, protože je dotazován dvakrát (jednou pro každé spojení).

To není správné řešení. PHPCG používá pokročilý systém filtrů, který umožňuje vyhledávat a filtrovat záznamy v seznamech, ale nepodporuje používání aliasů pro tabulky.

Existují dvě alternativní řešení.


První řešení: změna struktury databáze

Ve výše uvedeném příkladu tabulka persons sdružuje v jedné tabulce dvě různé entity: manažery a zaměstnance.

To není dobrý nápad. Vždy je lepší vytvořit tabulku pro každý datový typ (každou entitu).

MySQL two joins to two distinct tables
Příklad tabulky MySQL se dvěma připojeními ke dvěma různým tabulkám

Druhé řešení: ruční úprava dotazu SQL seznamu READ

Vezměme si trochu jinou strukturu:

MySQL two joins to the same table example 2
Tabulka MySQL se dvěma spojeními do stejné tabulky - příklad 2

V tomto druhém případě se tabulka projektů týká dvou zaměstnanců.
Nebylo by konzistentní vytvářet dvě tabulky pro zaměstnance, protože zaměstnanci představují jedinečnou entitu.

Řešením je upravit třídu PHP, která vytváří zaměstnance, a nahradit dotaz generovaný generátorem dvěma samostatnými dotazy.

Zde je návod, jak to udělat:

  1. Otevřete soubor admin/class/crud/Projects.php v editoru kódu.
    (nahraďte Projects názvem vaší tabulky)
  2. Najděte v kódu dotaz a odstraňte pole a spojení, které odkazují na druhé spojení.
    Spojovací část dotazu začíná slovy $this->join_query = ' LEFT JOIN ...' a část s poli začíná slovy $qry_start = 'SELECT ...'.
  3. Najděte část kódu, kde jsou záznamy zaregistrovány. Začíná slovy while (!$db->endOfSeek()) { ...
  4. V této smyčce odstraňte výsledky, které se vztahují k druhému spojení.
  5. Po smyčce přidejte novou, která se zacyklí uvnitř všech záznamů a získá záznamy z druhého spojení.
    V našem příkladu by to bylo:
    for ($i=0; $i < $this->records_count; $i++) {
                $qry = 'SELECT `employees`.`id` AS `employees_id`, `employees`.`name` AS `employees_name` FROM projects
                LEFT JOIN `employees` ON `projects`.`employees2_id`=`employees`.`id`
                WHERE projects.id = ' .  $this->id[$i] . ' LIMIT 1';
                $db = new DB();
                $db->query($qry);
                $db_count = $db->rowCount();
                if (!empty($db_count)) {
                    $row = $db->fetch();
                    $this->employees2_id[] = $row->employees_id . '[|]' . $row->employees_name;
                } else {
                    $this->employees2_id[] = '';
                }
            }

Pokud po provedení těchto vlastních změn v kódu budete muset později znovu vytvořit seznam READ z generátoru, nezapomeňte, že je k dispozici nástroj Porovnání souborů:
(Jak používat nástroj pro porovnávání souborů v generátoru CRUD).

Toto řešení samozřejmě vyžaduje určité znalosti kódování, pokud potřebujete pomoc, kontaktujte nás a my se budeme snažit.

Hlavní stránka výukového programu PHP CRUD