Sestavení JOIN dotazu v Nette\Database

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

Zdravím,
potřeboval bych poradit se sestavením dotazu na MySQL databázi pomocí Nette\Database. Vůbec si nevím rady. Zkusím vše popsat co nejlépe, rád Vás doplním, aby jste to pochopili :)

Mám následující 4 tabulky:

adresy
id
okres (odkazuje na id z tabulky okresy)
name
okresy
id
name
produkty
id
name
type
adresy_produktu
id
produkt (odkazuje na id z tabulky produkty)
adresa (odkazuje na id z tabulky adresy)

Potřeboval bych sestavit dotaz, který bude umět toto:
Vybrat z tabulky produkty takové záznamy, které mají hodnotu type = 0 nebo type = 3, to samozřejmě problém není. K tomu navíc záznamy, které mají type = 1 nebo type = 2 a ukazuje na ně záznam z tabulky adresy_produktu, který má hodnotu adresa.okres = ?

Jedná se pravděpodobně o JOIN příkaz, ale netuším, jak ho použít.
Nevíte někdo, prosím? Nemám ani páru jak na to a byl bych moc rád za nějaké řešení :)

Děkuji mnohokrát

Eda
Backer | 220
+
0
-

Zkus tohle :-)

$table = $this->db->table('produkty');
$selection = $table->where("
	(type IN ?) OR
	(type IN ? AND :adresy_produktu.adresa.okres = ?)
", [0, 3], [1, 2], $okresId);

Editoval Eda (28. 1. 2014 0:29)

fobák
Člen | 5
+
0
-

No něco podobného už se mi podařilo dát do kupy, ale hází to chybu:

No reference found for $service->service_addres.

Eda
Backer | 220
+
0
-

Divné.

  • zkontroluj, zda používáš DiscoveredReflection
  • zkontroluj, zda jsou správně nastavené cizí klíče v DB
  • používáš Nette 2.1? V předchozích verzích je syntaxe kapánek jiná
fobák
Člen | 5
+
0
-

Eda napsal(a):

Divné.

  • zkontroluj, zda používáš DiscoveredReflection
  • zkontroluj, zda jsou správně nastavené cizí klíče v DB
  • používáš Nette 2.1? V předchozích verzích je syntaxe kapánek jiná

Aha, používám Nette 2.0. Takže by byl problém tady?

Eda
Backer | 220
+
0
-

V tom případě dvojtečka bude až za názvem navázané tabulky.

$table = $this->db->table('produkty');
$selection = $table->where("
	(type IN ?) OR
	(type IN ? AND adresy_produktu:adresa.okres = ?)
", [0, 3], [1, 2], $okresId);
xxxmisko
Člen | 140
+
0
-

ja mám otázku. Čo, ak nemám tabuľky previazané, ale primárne kľúče sú v poriadku. Skrátka chýbajú cudzie kľúče, pričom db meniť nebudem.

Skrátka: chcel by som vynútiť left join 2 tabuliek, ktoré nemajú medzi sebou väzbu, ale aj tak by som ich chcel prepojiť. Ako na to? Tiež mi to totiž hádže chybu: No reference found.

Je možné to nejako zautomatizovať, alebo si musím napísať vlastný dotaz?
Ďakujem

Robyer
Člen | 74
+
0
-

Možná takto? Z dokumentace:

To make join over translator_id, just provide optional “parameter” into “joining expression”.

$selection = $context->table('author');
$selection->group('author.id')
          ->having('COUNT(:book(translator).id) > 3')
fobák
Člen | 5
+
0
-

Eda napsal(a):

V tom případě dvojtečka bude až za názvem navázané tabulky.

$table = $this->db->table('produkty');
$selection = $table->where("
	(type IN ?) OR
	(type IN ? AND adresy_produktu:adresa.okres = ?)
", [0, 3], [1, 2], $okresId);

Toto řešení sice hledá produkty podle polohy v případě type = 1, nebo type = 2, ale nezobrazují se produkty s type = 0 a type = 3

Eda
Backer | 220
+
0
-

Hoď sem SQL, co to vygenerovalo. Mělo by to fungovat.

fobák
Člen | 5
+
0
-
SELECT `produkty`.`id`, `produkty`.`kategorie`, `produkty`.`url`, `produkty`.`nazev`, `produkty`.`popis`
FROM `produkty`
INNER JOIN `adresy_produktu` ON `produkty`.`id` = `adresy_produktu`.`produkty`
INNER JOIN `adresa` ON `adresy_produktu`.`adresa` = `adresa`.`id`
WHERE ((`type` IN (0, 3)) OR (`type` IN (1, 2) AND `adresa`.`okres` = 77))
Eda
Backer | 220
+
0
-

Aha, tak s tím asi nehneme :-( Ve 2.0 to vlastně ještě generuje INNER JOINy.

Takže asi doporučím jedině přejít na 2.1, nebo to vyřešit nějakým takovýmto SUBSELECTEM.

$table = $this->db->table('produkty');
$selection = $table->where("
  (type IN ?) OR
  (type IN ? AND EXISTS (
	SELECT adresa
	FROM `adresy_produktu`.
	INNER JOIN `adresy` ON `adresy_produktu`.`adresa` = `adresy`.`id`
	WHERE `adresy_produktu`.`produkt` = `produkty`.`id`
	  AND `adresy`.`okres` = ?
  ))
", [0, 3], [1, 2], $okresId);

Editoval Eda (28. 1. 2014 18:47)