LEFT JOIN filtrování podle více parametrů

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

Zdravím … potřebuju naťuknout. Já prostě pořád tu nette databázi nemám pod kůží

Mám tabulku variant produktů se sloupcemi id,popis

varianta(id, popis)

a tabulka parametrů variant

varianta_parametr(id, varianta_id, parametr_id, hodnota_id)

parametr_id a hodnota_id jsou cizí klíče do tabulek, kde jsou parametry a jejich hodnoty definované – to ale není podstatné

Potřeboval bych udělat dotaz, který mi vybere všechny varianty, které mají v tabulce parametrů záznam parametr_id=5 a hodnota_id=35 a zároveň mají záznam parametr_id=11 a hodnota_id=122

Pokud bych chtěl filtrovat pouze podle prvního požadavku tak udělám

<?php
$selection=$connection->table('varianta')->where(':varianta_parametr.parametr_id=5 AND :varianta_parametr.hodnota_id=35')
?>

Ale jak to udělat aby mi fungovaly oba požadavky … přes další where už cesta nevede takže se musí asi přes HAVING, ale za boha na to nemůžu přijít.

Díky moc

Mysteria
Člen | 797
+
0
-

Takhle jednoduše to nefunguje?

->where(':varianta_parametr.parametr_id=5 AND :varianta_parametr.hodnota_id=35 AND :varianta_parametr.parametr_id=11 AND :varianta_parametr.hodnota_id=122')

Having určitě ne, protože to je na podmínky pro agregační funkce typu COUNT a podobně.

Editoval Mysteria (16. 9. 2016 8:44)

CZechBoY
Člen | 3608
+
0
-

Přidat bych

->group('varianta_id')
->having('COUNT(parameter_id)', 2);
group by varianta_id having count(parametr_id) = 2

@Mysteria to nedává smysl, jak můžeš mít v jednom řádku v jedný tabulce dvě hodnoty pro jeden sloupec? Když už tak by to chtělo přidat další join na tu stejnou tabulku variant.

Editoval CZechBoY (16. 9. 2016 8:59)

sejmor
Člen | 63
+
0
-

@Mysteria to by fungovalo v případě, že by parametry byly ve sloupcích. Oni jsou ale v řádcích a já v podstatě potřebuji zjistit jestli pro danou variantu jsou zmíněné dva řádky (dva parametry s konkrétní hodnotou)… což právě asi vyžaduje HAVING

@CZechBoY … nějak takhle to bude. Pokud tomu rozumím tak tvé řešení chápu jako že agreguji výsledky, které mají 2 řádky. Ale já tam potřebuji dostat i tu druhou podmínku a nevím kam.

CZechBoY
Člen | 3608
+
+1
-

@sejmor ajo zapomněl jsem ti tam přidat OR

$parameterFilterWhere = ':varianta_parametr.parametr_id=? AND :varianta_parametr.hodnota_id=?';
$selection = $context->table('varianta')
->where("(({$parameterFilterWhere}) OR ({$parameterFilterWhere}))", 5, 35, 11, 122);
->group('varianta.varianta_id')
->having('COUNT(:varianta_parametr.parametr_id)', 2);

edit: odebráno pole parametrů pro where a použity variabilní parametry

Editoval CZechBoY (16. 9. 2016 11:50)

sejmor
Člen | 63
+
0
-

pokud se nepletu tak potřebuji tento dotaz

select * from varianta
LEFT JOIN varianta_parametr as p1 on p1.parametr_id=5 AND p1.hodnota_id=35 AND p1.varianta_id=varianta.id
LEFT JOIN varianta_parametr as p2 on p2.parametr_id=11 AND p2.hodnota_id=122 AND p2.varianta_id=varianta.id
WHERE p1.parametr_id=5 AND p1.hodnota_id=35 AND p2.parametr_id=11 AND p2.hodnota_id=122
CZechBoY
Člen | 3608
+
0
-

To je ta druhá varianta co jsem psal, nebo můžeš přes ten group by + having.

sejmor
Člen | 63
+
0
-

@CZechBoY Vypadá to že to bude ono (parametry pro where v hranatých závorkách mi nejdou) … dal jsem následující dotaz:

$parameterFilterWhere = ':varianta_parametr.parametr_id=? AND :varianta_parametr.hodnota_id=?';
$this->varianty=$context->table('varianta')
->where("(({$parameterFilterWhere}) OR ({$parameterFilterWhere}))",5,35,11,122)
->group('varianta.id')
->having('COUNT(:varianta_parametr.parametr_id)=2')
->order('varianta.id');

A hází mi správný výsledky jako ten můj napsaný SQL dotaz… teď to jenom obalit a správně dynamicky sestavit ten where podle počtu vyplněných parametrů, ale to už bude doufám rutina

DÍKY MOC !

sejmor
Člen | 63
+
0
-

@CZechBoY … ještě jenom jeden dotaz – vrtá mi to hlavou. Jde o ten druhý způsob řešení v nette DB. Jak píšeš „další join na tu stejnou tabulku variant“ … v podstatě abych mi to vygenerovalo ten můj SQL dotaz bez GROUP a HAVING. Jak ho donutím aby udělal 2 x LEFT JOIN na stejnou tabulku ? Jde mi o pochopení :)

norbe
Backer | 405
+
+3
-

Píšu z hlavy, ale mělo by jít zhruba takto:

$context->table('varianta')
		->alias(':varianta_parametr', 'p1')
		->alias(':varianta_parametr', 'p2')
//		->joinWhere('p1', 'p1.parametr_id', 5)
//		->joinWhere('p1', 'p1.hodnota_id', 35)
//		->joinWhere('p2', 'p2.parametr_id', 11)
//		->joinWhere('p2', 'p2.hodnota_id', 122)
		->where('p1.parametr_id', 5)
		->where('p1.hodnota_id', 35)
		->where('p2.parametr_id', 11)
		->where('p2.hodnota_id', 122);

JoinWhere jsem zakomentoval, jelikož dle mého není potřeba.

Edit: Předpokládá nette database v 2.4+

Editoval norbe (16. 9. 2016 14:16)

sejmor
Člen | 63
+
0
-

díky moc … asi budu muset překlopit na nette 2.4 když tam jsou takovýhle vychytávky :)