Dotahování dat z jiné spojené tabulky
- petrf
- Člen | 15
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
@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
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
@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
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.