Dotahování dat z jiné spojené tabulky

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
petrf
Člen | 15
+
0
-

Zdravím,
poslední dobou řeším následující problém s NDB/T:

Mám spojené tabulky city a place, zachované konvence. Místa ukazují na města, typické 1:N.
CREATE TABLE city (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE place (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
city_id int(11) unsigned NOT NULL,
PRIMARY KEY (id),
KEY city_id (city_id),
CONSTRAINT place_ibfk_1 FOREIGN KEY (city_id) REFERENCES city (id) ON UPDATE CASCADE
) ENGINE=InnoDB;

Potřebuji dohledat ID města podle ID místa.
Dělá problém získání hodnot z jiné tabulky.

Můj problém sice dokáže vyřešit

$row = $this->db->query('SELECT c.id AS city_id FROM city c JOIN place p ON c.id = p.city_id WHERE p.id = ?', $placeId)->fetch();

ale říkám si, že to není zrovna to pravé ořechové.

Zkoušel jsem něco jako :

$row = $this->db->table(TABLE_PLACE)
	->where(TABLE_CITY . "."  . ID . " = " . TABLE_PLACE . "." . CITY_ID)
	->where(TABLE_PLACE . "." . CITY_ID . " = ?", $placeId)
	->select(TABLE_CITY . "." . ID  . " AS " . 'cityId')
	->fetch();   // dump($row);

To sice projde, ale nic do $row[‚cityId‘] nevrátí.

Prohodit tabulky (udělat backjoin) $this->db->table(TABLE_CITY) jsem taky zkoušel,
ale to zařve, že nemůže najít referenci

Ale např. obrácený převod z měst na místa funguje v pořádku, ale ten nepotřebuju:

		$row = $this->db->table(TABLE_PLACE)
			->where(CITY_ID, $cityId)
			->order(ID)
			->fetchAll();

Nevím, co dělám špatně, nebo špatně chápu princip NDBT/NotORM (dělám v NDBT tom pár týdnů).

Díky

Editoval petrf (19. 7. 2015 10:07)

chemix
Nette Core | 1310
+
0
-

@petrf nehledas nahodou „The reverse relationships is also possible. We call it backjoin“

https://doc.nette.org/…ase/explorer

$selection = $context->table('author');
$selection->group('author.id')
          ->having('COUNT(:book.id) > 3');

Pouziva se tam ta dvojtecka, ja to objevil min tyden kdy jsem se potreboval dostat k datum z „rodicovske“ tabulky v m:n vazbach

// ps necetl jsem cele zadani jsem na telefonu, tak snad nejsem uplne mino ;-)

petrf
Člen | 15
+
0
-

Ano, díky. Tvá odpověď přišla zrovna v době, kdy jsem to opravil :)

Občas si stačí pořádně pročíst Dokumentaci
Je škoda, že Selection ještě není tak chytrá, aby uměla i obrácené spojení – začátečníci (like me) v tom potom docela tápou. Možná proto, že obyčejné spojení má syntaxi podobnou SQL, jen JOIN za ně udělá stroj, ale u obráceného spojení musí groupovat, havingovat, dvojtečkovat, kdežto v obyčejném SQL ne.

$row = $this->db->table(TABLE_CITY)
	->group(':' . TABLE_PLACE . '.' . ID)
	->having(ID . ' = ?', $placeId);

if ($row) {
	foreach ($row as $rows) {
		dump($rows[ID]);
	}
}

Editoval petrf (19. 7. 2015 10:40)

chemix
Nette Core | 1310
+
0
-

@petrf to neni az takova pravda, ja to pouzivam bez group ci havingu jen jako join, najdu pak kus kodu u pocitace

Mysteria
Člen | 797
+
0
-

Proč místo GROUP BY + HAVING nepoužiješ normální WHERE? Z hlavy:

if (count($cities = $this->database->table('city')->where(':place.id = ?', $ID))) {
	foreach ($cities as $city) {
		dump($city);
	}
}

Editoval Mysteria (19. 7. 2015 11:20)

chemix
Nette Core | 1310
+
0
-

@petrf ja to treba pouzivam takto :

$db->table('project')->findAll()
	->where(':project_mutation.name LIKE ?
				OR project.code LIKE ?
				array(
					"%" . $query . "%",
					"%" . $query . "%")
			);

vysledek je pak neco jako

SELECT `project`.`id`, `project`.`year`
FROM `project`
LEFT JOIN `project_mutation` ON `project`.`id` = `project_mutation`.`project_id`
WHERE (`project_mutation`.`name` LIKE '%blue%'
 OR `project`.`code` LIKE '%blue%'
 OR `project`.`custom_column_a` LIKE '%blue%')
petrf
Člen | 15
+
0
-

Mysteria napsal(a):

Proč místo GROUP BY + HAVING nepoužiješ normální WHERE? Z hlavy:

if (count($cities = $this->database->table('city')->where(':place.id = ?', $ID))) {
	foreach ($cities as $city) {
		dump($city);
	}
}

Protože jsem dříve dělal v DiBi a NDBT zkouším prvně a nevěděl jsem o tomto způsobu. Dokumentace /database-selection uvádí pouze tři příklady na backjoin 1:N, a všechny jsou dělány pomocí group s podmínkou having.

Mysteria
Člen | 797
+
0
-

Jn, ale to je jenom kvůli tomu, že všechny ty příklady jsou založené na počtu zgroupovaných položek. Samozřejmě možná by stálo za to, tam dát i „normální“ příklad. :)