Dvojite vztahy mezi tabulkami

- jednou
 - Člen | 14
 
Ahoj,
resim pripad, podobny strukture https://doc.nette.org/…ase/explorer
Konkretne:

V tabulce Author je vazba na Adresu autora/maintainera.
CREATE TABLE `address` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT;
CREATE TABLE `author` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) NOT NULL,
  `address_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `address_id` (`address_id`),
  CONSTRAINT `author_ibfk_1` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`)
) ENGINE=InnoDB DEFAULT;
Kdyz chci zobrazit adresy autora a maintainera, tak mi to spatne vygeneruje vazbu do tabulky Address.
table(book)->select(title, author.address.name, maintanier.address.name)
SELECT `title`,`address`.`name`,`address`.`name`
FROM `book`
LEFT JOIN `author` ON `book`.`author_id` = `author`.`id`
LEFT JOIN `address` ON `maintainer`.`address_id` = `address`.`id`
LEFT JOIN `author` AS `maintainer` ON `book`.`maintainer_id` = `maintainer`.`id`
Ocekaval bych tohle:
SELECT `title`,`author_address`.`name`,`maintainer_address`.`name`
FROM `book`
LEFT JOIN `author` ON `book`.`author_id` = `author`.`id`
LEFT JOIN `author` AS `maintainer` ON `book`.`maintainer_id` = `maintainer`.`id`
LEFT JOIN `address` AS `author_address` ON `author`.`address_id` = `author_address`.`id`
LEFT JOIN `address` AS `maintainer_address` ON `maintainer`.`address_id` = `maintainer_address`.`id`
Je to featura nebo bug? Delam neco spatne?

- jednou
 - Člen | 14
 
Pridal jsem aliasy. Error hlaska stale stejna:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'maintainer.address_id' in 'on clause'
vygenerovane sql:
SELECT `title`,`address`.`name` AS `author_address`,`address`.`name` AS `maintainer_address`
FROM `book`
LEFT JOIN `author` ON `book`.`author_id` = `author`.`id`
LEFT JOIN `address` ON `maintainer`.`address_id` = `address`.`id`
LEFT JOIN `author` AS `maintainer` ON `book`.`maintainer_id` = `maintainer`.`id`
				
- jednou
 - Člen | 14
 
Ok, pridávám tedy SQL pro tabulku Book:
CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author_id` int(11) NOT NULL,
  `maintainer_id` int(11) NOT NULL,
  `title` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `author_id` (`author_id`),
  KEY `maintainer_id` (`maintainer_id`),
  CONSTRAINT `book_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`),
  CONSTRAINT `book_ibfk_2` FOREIGN KEY (`maintainer_id`) REFERENCES `author` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Volam to v presenteru takhle:
$res = $this->database->table("book")->select("title,author.address.name AS author_address,maintainer.address.name AS maintainer_address");
$a = $res->fetch();
					Editoval jednou (27. 6. 2016 13:54)

- Felix
 - Nette Core | 1271
 
Tak jsem si to pro jistotu zkusil i u sebe a je fakt ze to nejde. Ale nejsem si jisty, ze je to bug. To by musel odpovedet nekdo kdo nette/database zna do hloubky. (@dg, @DavidMatějka, @hrach, ..)
Tohle projde v pohode, ale udela to 5 dotazu.
foreach ($context->table('book') as $book) {
	echo $book->author->address->name;
	echo $book->maintainer->address->name;
}
- SELECT 
id,author_id,maintainer_idFROMbook - SELECT 
id,address_idFROMauthorWHERE (idIN (1)) - SELECT 
id,nameFROMaddressWHERE (idIN (1)) - SELECT 
id,address_idFROMauthorWHERE (idIN (2)) - SELECT 
id,nameFROMaddressWHERE (idIN (2)) 
To je asi nezadouci.

- Unlink
 - Člen | 298
 
S najnovšou nette database sa to dá spraviť takto
$res = $this->database->table("book")
->select("title,author.address.name AS author_address,ma.name AS maintainer_address")
->alias('maintainer.address', 'ma');
$a = $res->fetch();
Výsledné SQL
SELECT `title`, `address`.`name` AS `author_address`, `ma`.`name` AS `maintainer_address`
FROM `book`
LEFT JOIN `author` `author` ON `books`.`author_id` = `author`.`id`
LEFT JOIN `address` ON `author`.`address_id` = `address`.`id`
LEFT JOIN `author` `maintanier` ON `books`.`maintanier_id` = `maintanier`.`id`
LEFT JOIN `address` `ma` ON `maintanier`.`address_id` = `ma`.`id`
V staršej by tvoj kód fungovať mal, akú verziu presne používaš?
Editoval Unlink (27. 6. 2016 14:13)

- norbe
 - Backer | 408
 
Ono to bude fungovat v jakékoli verzi, ale nesmíš tam mít překlep,
aspoň teda předpokládám, nezkoušel jsem :-) maintanier
vs maintainer
Edit: Blbost špatně jsem se podíval na to kde je problém. Podle mne to můžeš obejít tak, že místo druhého address dáš jen addres, tzn.
$this->database->table("book")->select("title,author.address.name AS author_address,maintainer.addres.name AS maintainer_address");
					Editoval norbe (27. 6. 2016 15:41)

- jednou
 - Člen | 14
 
@norbe: S pouzitim „addres“ misto „address“ to obejit nejde. Výsledek:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'address.name' in 'field list'
SELECT `title`,`address`.`name` AS `author_address`,`addres`.`name` AS `maintainer_address`
FROM `book`
LEFT JOIN `author` ON `book`.`author_id` = `author`.`id`
LEFT JOIN `address` AS `addres` ON `maintainer`.`address_id` = `addres`.`id`
LEFT JOIN `author` AS `maintainer` ON `book`.`maintainer_id` = `maintainer`.`id`
				
- blaztar
 - Člen | 93
 
Z dokumentace:
Hlavní myšlenkou je načítání dat pouze z jedné tabulky a tak, aby se
tyto dotazy pokládaly jen jednou.
Což bych převedl na:
function renderBook()
{
	$this->template->book = $this->db->table('book')->get(1); // id záznamu
}
title: {$book->title}
author: {$book->author->name}
address: {$book->author->address->name}
maintainer: {$book->ref('author', 'maintainer_id')->name}
maintainer: {$book->ref('author', 'maintainer_id')->address->name}
				
- blaztar
 - Člen | 93
 
Jen píšu na co je Nette Database stavěná, ale třeba to půjde.
Nebo použít query:
$this->db->query("
	SELECT title, address.name AS author_address, ma.name AS maintainer_address
	FROM book
	LEFT JOIN author author ON book.author_id = author.id
	LEFT JOIN address ON author.address_id = address.id
	LEFT JOIN author maintainer ON book.maintainer_id = maintainer.id
	LEFT JOIN address ma ON maintainer.address_id = ma.id
")->fetchAll();
					Editoval blaztar (27. 6. 2016 19:14)

- CZechBoY
 - Člen | 3608
 
@jednou No buď si forkneš Nette/Database a doděláš si tam podporu nebo použiješ 2.4 RC nebo můžeš použít https://github.com/…rts/database