Autor | Zpráva | ||
---|---|---|---|
lopikol Profil |
#1 · Zasláno: 10. 7. 2011, 01:14:43 · Upravil/a: lopikol
SELECT M.*, GD.*, G.name AS genres FROM movies M LEFT JOIN genres_data GD ON GD.movies_id = M.id LEFT JOIN genres G ON G.id = GD.genres_id GROUP BY M.id ORDER BY M.id Problém je vom, že výpis z `G.name AS genres` je array, ale dibi nebo nette mi vypíše pouze úplně ten první. Co mám do dotazu připsat nebo co upravit, aby to vypsalo všechny `G.name AS genres` > všechny žánry daného filmu. Děkuji |
||
o_O Profil |
#2 · Zasláno: 10. 7. 2011, 03:03:01
lopikol:
Jakub vrána - group_concat |
||
lopikol Profil |
#3 · Zasláno: 11. 7. 2011, 20:32:19
o_O:
Díky, ale díky tomu vzniká jeden problém. Vytvoří to skupinu: bmw,fiat,audi,škoda. Jenže už sní nemohu nijak pracovat > např, když bych chtěl vybrat jen audi. |
||
panther Profil |
#4 · Zasláno: 11. 7. 2011, 20:33:44
lopikol:
buď chceš vybrat všechny, nebo jen audi. To jsou dva různé dotazy. Případně si můžeš data groupovat na úrovni PHP aplikace. |
||
lopikol Profil |
#5 · Zasláno: 11. 7. 2011, 21:16:17
jenže když nepoužiju group_concat, tak mi to vypíše jen první záznam > BMW a tím to končí.
|
||
o_O Profil |
#6 · Zasláno: 11. 7. 2011, 21:16:41
lopikol:
„Jenže už sní nemohu nijak pracovat“ Můžete. Stačí použít např. funkci explode(), popřípadě by šlo upravit dotaz, jen musíte specifikovat co přesně musí příkaz dodat. |
||
Tori Profil |
#7 · Zasláno: 11. 7. 2011, 22:03:50 · Upravil/a: Tori
lopikol:
„výpis z `G.name AS genres` je array, ale dibi nebo nette mi vypíše pouze úplně ten první.“ Nějak to nechápu - mělo by vám to prostě vracet postupně všechny hodnoty (názvy žánrů nebo co), jen bude každý na jiném řádku. Jestli používáte dibi, podívejte se na příklady s fetchAssoc - třeba se bude dát použít něco jako $vysledek = dibi::query("SELECT M.*, M.id AS 'movie_id', GD.*, G.name AS 'genres', G.id AS 'genre_id' FROM movies M LEFT JOIN genres_data GD ON GD.movies_id = M.id LEFT JOIN genres G ON G.id = GD.genres_id GROUP BY M.id ORDER BY M.id")->fetchAssoc('movie_id,=,genre_id'); |
||
lopikol Profil |
#8 · Zasláno: 12. 7. 2011, 13:19:17
Tori:
Právě, že já to taky nechápu. Prostě mi to vypíše jen ten první jak jsem říkal a né všechny :( „fetchAssoc“ Zkoušel jsem snad všechny možnosti a nejde to. |
||
o_O Profil |
#9 · Zasláno: 12. 7. 2011, 18:56:20
Stále nechápu, čeho chcete dosáhnout. Řekl jste, že potřebujete vybrat „všechny žánry daného filmu“, což group_concat udělal.
Mohl by jste říci, čeho přesně chcete dosáhnout? Bez této informace Vám nemůžeme poradit. |
||
lopikol Profil |
#10 · Zasláno: 12. 7. 2011, 19:14:20
GROUP_CONCAT(G.name ORDER BY G.name) AS genres Chci dosáhnout toho, abych s daty z téhle části dotazu mohl pracovat jednotlivě. To jest. genres vypíše řadu akční,krimi,thriller. Jenže, díky tomu je to skupina, a tak nemohu např vybrat jen filmy, které mají žánr katastrofický. |
||
o_O Profil |
#11 · Zasláno: 12. 7. 2011, 19:46:42
Jediné, co mě v tuto chvíli napadá je využít HAVING.
Př: SELECT M.*, GD.*, group_concat(G.name) AS genres FROM movies M LEFT JOIN genres_data GD ON GD.movies_id = M.id LEFT JOIN genres G ON G.id = GD.genres_id GROUP BY M.id having genres LIKE '%Komedie%' ORDER BY M.id Ovšem LIKE dost zpomaluje (zvláště u větší tabulky), možná by to šlo napsat lépe. Popřemýšlím o tom, prozatím by šlo využít toto (doporučuji si pohrát s indexy). |
||
lopikol Profil |
#12 · Zasláno: 12. 7. 2011, 21:30:41 · Upravil/a: lopikol
Tak jsem trochu bádal.
Pokud použiju having, tak to vypíše jen ty, kde je první žánr komedie tzv. ?having=1 (id komedie) a vypíše to všechny filmy, kde je pořadí žánrů Komedie, Rodinný, Animovaný, ale pokud je pořadí žánrů Animovaný, Komedie, Rodinný, tak ho to nezobrazí. Zkusil jsem použít i where, ale to zas vypíše jen ten daný žánr, ale vybere to všechny filmy s vybraným žánrem. Např. mám film Auta žánr Rodinný, Komedie, Animovaný. V url mám ?where=1 (id komedie) a na stránce se zobrazí Auta - komedie > nevypíše to další žánry rodinný, animovaný Řešením bude nějak nahradit GROUP_CONCAT(), jenže bez toho mi to ty žánry nevypíše všechny. $m = dibi::select('M.name, M.time, M.link, GROUP_CONCAT(G.name ORDER BY G.name) AS genres, Q.name as mquality, G.id AS gid, GD.genre_id AS gdid') ->from('[::movies] M') ->leftJoin('[::genres_data] GD') ->on('GD.movie_id = M.id') ->leftJoin('[::genres] G') ->on('G.id = GD.genre_id') ->leftJoin('[::qualities] Q') ->on('Q.id = M.quality_id') ->groupBy('M.id'); if($having) { $m->having('G.id LIKE %i', $having); } if($sort_desc) { $m->orderBy(array($sort_by => 'DESC')); }else{ $m->orderBy($sort_by); } $m->test(); return dump($m->fetchAll()); |
||
o_O Profil |
#13 · Zasláno: 12. 7. 2011, 22:46:33
lopikol:
„Pokud použiju having, tak to vypíše jen ty, kde je první žánr komedie“ Můj příklad s HAVING funguje i v případě, že se daný žánr vyskytuje uprostřed skupiny. Pravděpodobně jste ho špatně opsal (chybějící %). |
||
lopikol Profil |
#14 · Zasláno: 13. 7. 2011, 01:23:41
o_O:
Moc děkuji za pomoc, jsem rád, že dnes ještě někdo pomůže ;) Vyřešil to %~like~ |
||
lopikol Profil |
#15 · Zasláno: 13. 7. 2011, 09:53:34 · Upravil/a: lopikol
Chtěl jsem si vytvořit tzv multiple choice, Zaškrtneš více kategorií a vybere je to z db. Přidal jsme do kodu:
if($having) { $m->having('%or', array(array('genres LIKE %~like~', $having))); } Když do url zadám ?having=komedie nebo ?having=western, tak to najde správně jak má. Když zadám ?having=komedie&having=western, tak se to zkrátí na ?having=western a jsem zase na začátku. Jak bys to řešil? Ještě jsem došel k jednomu problému. A to, když je fiml spadá pod žánr akční nebo romantický, ale to snad vyřešim. |
||
o_O Profil |
#16 · Zasláno: 13. 7. 2011, 11:36:53
V případě, že se vybere více možností, má to vybírat film v případě přesné shody (tzn. film musí mít žánry Western a Komedie), nebo musí obsahovat právě jeden z vybraných žánrů?
Co se týče odkazu, je jasné, že nelze používat 2× stejný klíč (having a having), ale musí se z něj udělat pole (having[]), tzn: <form action="" method="get"> <select name="having[]"><option value="western">Western</option><option value="komedie">Komedie</option></select> <select name="having[]"><option value="akcni">Akční</option><option value="romanticky">Romantický</option></select> <input type="submit" name="odeslat" value="Vyhledat"></form> |
||
o_O Profil |
#17 · Zasláno: 13. 7. 2011, 11:43:55
* Výstup pak bude: Array ( [having] => Array ( [0] => western [1] => akcni ) [odeslat] => Vyhledat )
* URL pak bude: ?having[]=western&having[]=akcni&odeslat=Vyhledat lopikol: „Ještě jsem došel k jednomu problému“ Jakému? LIKE nemá rádo diakritiku? |
||
lopikol Profil |
#18 · Zasláno: 13. 7. 2011, 12:32:58 · Upravil/a: lopikol
o_O:
„V případě, že se vybere více možností, má to vybírat film v případě přesné shody (tzn. film musí mít žánry Western a Komedie), nebo musí obsahovat právě jeden z vybraných žánrů?“ Samozřejmě, že alespon jeden. Proto %or Část pro výběr vypadá takto: if($having) { dump($having); $m->having('%or', array(array('genres LIKE %~like~', $having))); } Výsledné SQL: array(2) [ 0 => "western" (7) 1 => "komedie" (7) ] SELECT M.name, M.time, M.link, GROUP_CONCAT(G.name ORDER BY G.name) AS genres, Q.name as mquality FROM `movies` M LEFT JOIN `genres_data` GD ON GD.movie_id = M.id LEFT JOIN `genres` G ON G.id = GD.genre_id LEFT JOIN `qualities` Q ON Q.id = M.quality_id GROUP BY `M`.`id` HAVING (genres LIKE '%western%', '%komedie%') ORDER BY `name` Jak je vidět, tak řádek HAVING je špatně. Bohužel, to nemohu dát dohromady. „Jakému? LIKE nemá rádo diakritiku?“ No url nemá rádo diakritiku z akční udělá akn |
||
o_O Profil |
#19 · Zasláno: 13. 7. 2011, 12:52:03
Prosím, posílejte zde alespoň společně s příkazem i strukturu tabulek. Jak se tak koukám, dost se změnila a já to díky toho nemohu odzkoušet v PMA.
Co se týče toho problému, chyba je jasná: Operand should contain 1 column. To znamená, že musíte využít 2 LIKE. Stačí to upravit na: HAVING (genres LIKE '%western%' OR genres LIKE '%komedie%') |
||
lopikol Profil |
#20 · Zasláno: 13. 7. 2011, 13:10:22
Tu je to sql. Moc se nezměnilo.
DROP TABLE IF EXISTS `genres`; CREATE TABLE `genres` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` tinytext COLLATE utf8_czech_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci; DROP TABLE IF EXISTS `genres_data`; CREATE TABLE `genres_data` ( `movie_id` int(11) NOT NULL, `genre_id` int(11) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci; DROP TABLE IF EXISTS `movies`; CREATE TABLE `movies` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` tinytext COLLATE utf8_czech_ci NOT NULL, `time` int(11) NOT NULL, `quality_id` int(11) NOT NULL, `link` tinytext COLLATE utf8_czech_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci; DROP TABLE IF EXISTS `qualities`; CREATE TABLE `qualities` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` tinytext COLLATE utf8_czech_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci; o_O: > Stačí to upravit na: > > 1 > > HAVING (genres LIKE '%western%' OR genres LIKE '%komedie%') já myslel, že toto to dokáže. if($having) { dump($having); $m->having('%or', array(array('genres LIKE %~like~', $having))); } přeco tu musí jit jednodušeji, než psát: if($having[0]){HAVING (genres LIKE '%western%')} if($having[1]){HAVING (genres LIKE '%western%' OR genres LIKE '%komedie%') } if($having[2]){HAVING (genres LIKE '%western%' OR genres LIKE '%komedie%' OR genres LIKE '%si-fi%') } |
||
o_O Profil |
#21 · Zasláno: 13. 7. 2011, 13:17:27
lopikol:
„přeco tu musí jit jednodušeji“ Jestli to můžete napsat takto, tak jistě: if($_GET['having']){ $having=''; foreach($_GET['having'] AS $value) $having.='OR genres LIKE '%'.$value.'%'; } Do dotazu pak dosadíte string bez prvních 3 znaků (mb_substr($having,3)). |
||
o_O Profil |
#22 · Zasláno: 13. 7. 2011, 13:18:38
Eh, zapomněl jsem na apostrofy/uvozovky. Řekněme třeba takto:
if($_GET['having']){ $having=''; foreach($_GET['having'] AS $value) $having.='OR genres LIKE "%'.$value.'%"'; } |
||
Časová prodleva: 13 let
|
0