Problém s dotazem při spojování tabulek. Jak funguje JOIN?
- iskejp
- Člen | 41
Zdravím,
potřebuji poradit s chybou v dotazu do DB.
Dotaz v modelu:
SELECT `article_has_file`.`file_id`, `file`.`id`
FROM `article_has_file`
LEFT JOIN `file` ON `article_has_file`.`file_id` = `file`.``
WHERE (`article_has_file`.`article_id` = ?)
Vypíše chybu: SQLSTATE[42S22]: Column not found: 1054 Unknown column ‚file.‘ in ‚on clause‘
Není mi jasné proč se nedoplní file.id v části ON. Jak vlastně funguje sestavení JOIN dotazu?
Díky moc. Pokud to není jasné, rád upřesním.
- SendiMyrkr
- Člen | 30
na koncí tý řádky s ON máš „file
.``“
takže se snažíš vybrat jakoby z tabulky file sloupec bezejména…
edit.
sorry nedočetl jsem to celý… máš na tom sloupci id primary key?
Editoval SendiMyrkr (22. 10. 2012 1:29)
- iskejp
- Člen | 41
To Enumg: PHP v modelu je následující.
public function getFileUse ($articleId) {
return $this->select('article_has_file.file_id, file.id')->where('article_has_file.article_id = ?', $articleId);
}
To SendiMyrkr: Ano, id je PRIMARY KEY. Ještě pro jistotu dodávám, že mám aktuální verzi Nette 2.0.6.
- iskejp
- Člen | 41
Tak to jsem rád, že si to nemyslím sám :o).
Jinak model vypadá takto:
class AddFiles extends Selection {
public function __construct(Connection $connection)
{
parent::__construct('article_has_file', $connection);
}
public function insertFile ($articleId, $fileId, $userId) {
return $this->insert(array(
'article_id' => $articleId,
'article_user_id' => 1,
'file_id' => $fileId,
'file_user_id' => $userId
));
}
public function getFileUse ($articleId) {
return select('article_has_file.file_id, file.id')->where('article_has_file.article_id = ?', $articleId);
}
}
Pokud tam je něco špatně, rád se dozvím jak na to správně. Vycházel jsem z tutorialu.
A co se týče toho dotazu. Mám za to, že article_has_file.file_id vytáhne ID z N:N tabulky a spojí jej s file.id pro načtení dat o souboru.
Díky za pomoc.
- iskejp
- Člen | 41
Opět zdravím,
bohužel mi stále JOIN nefunguje. Nastudoval jsem změny modelů (jsou hezké), instaloval nejnovější verzi Nette, ale stále nic. Tentokrát mi hází chybu No reference found for $articleFile->articlefile.
Dotaz ve třídě ArticleFileRepository:
public function findFileUse ($articleId)
{
return $this->findWhere('articlefile.file_id='.$articleId);
}
Repository navazující na Quickstart:
public function findWhere($string)
{
return $this->getTable()->where($string);
}
Chybu v laděnce hlásí až render v komponentě při volání count:
public function render(){
$this->template->setFile(__DIR__.'/FileManage.latte');
$this->template->file = $this->fileManage;
$this->template->countFiles = count($this->fileManage);
$this->template->render();
}
Díky za pomoc.
- iskejp
- Člen | 41
Tak nakonec to nefunguje. Jelikož jsem změnou parametru WHERE zrušil JOIN. Dopracoval jsem se k hlášce:
PDOException #42S22
SQLSTATE[42S22]: Column not found: 1054 Unknown column ‚file.article_id‘ in
‚where clause‘
Dotaz do WHERE:
findWhere('file.article_id='.$articleId)
S tím, že výsledné SQL je:
`SELECT `articleFile`.*
FROM `articleFile`
INNER JOIN `file` ON `articleFile`.`file_id` = `file`.``
WHERE (`file`.`article_id`=13)`
Kde je chyba je mi jasné. V tabulce file žádný sloupec
article_id neexituje. Jenže pak nevím jak tedy vytvořit JOIN
2 tabulek. Navíc je podezřelé, že je prázdný řetězec
file
.``.
Můžete někdo poradit jak to vlastně funguje? Díky.
Editoval iskejp (12. 11. 2012 22:23)
- iskejp
- Člen | 41
Zdravím,
při pokusu o nalezení řešení problému se spojováním tabulek jsem vytvořil vlákno, které se postupem doby opět vyvinulo ve stejný problém. Myslím, že patří spíše sem.
https://forum.nette.org/…g-conversion#… (Na odkazu je výpis kódu a struktury DB.)
Při pokusech o nalezení řešení jsem přesunul dotaz do DB z ArticleFileRepository do FileRepository a změnil kód dotazu na tento:
return $this->findJoin('13:articlefile:file_id');
Vysvětlivka: 13 je pokusné ID článku ke kterému se mají připojit soubory. Dle mého pozorování má být na tomto místě $key a nikoli $table jak je uvedeno v návodu výše od enumaga.
Laděnka pak hlásí „Array to string conversion“ a toto:
...\libs\Nette\Database\Table\SqlBuilder.php:323 source ▼ Nette\Database\Drivers\MySqlDriver-> delimite (arguments ▼)
$name
array(2) ▼ [
0 => "id" (2)
1 => "user_id" (7)
]
Pokud se nepletu, je toto spíše funkční a správná cesta, které ovšem někde selhává. Bohužel nemohu vůbec přijít kde. Můžete opět poradit, či naťuknout?
Díky.
- iskejp
- Člen | 41
Zkusil jsem nasadit vývojovou verzi, ale je tam toho asi poměrně dost jiného a nepodařilo se mi to správně odladit :o(.
FindJoin vypadá takto:
public function findJoin($select/*, $where*/)
{
return $this->getTable()->select($select)/*->where($where)*/;
}
Zkoušel jsem jej bez části where, jelikož mi přišlo, že JOIN v Nette funguje buď přes WHERE, nebo přes SELECT, ale nikoli přes oboje.
EDIT: Nakonec jsem to vyřešil přes query.
Editoval iskejp (24. 12. 2012 16:45)