výběr řádků s databáze s velkým filtrem

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

Zdravím, chtěl bych se zeptat, jak nejlépe vybrat řádky při následující situaci ( výběr filtrovaných výsledků ) pomocí dibi.

response_id | text
_____________________
1 | honza
1 | pepa
1 | pavla
2 | honza
2 | jirka
3 | honza
3 | pepa
3 | ruda
_____________________

Nu a potřebuji udělat následující: Vybrat všechny řádky za podmínky:

response_id | text obsahuje honza
a zároveň
response_id | text obsahuje pepa

Tedy vybrat všechny řádky s response_id 1 a 3.

Stupidně by to šlo jako vybrat všechny řádky, které obsahují honza, pak pepa, pak zkontrolovat, které vyhovují tomu, že obsahují oba a pak vybrat všechny řádky těch response_id, kde jsou ti oba.

Ovšem pokud budu mít podmínek hodně, tak je to strašně neefektivní. Nějak mě nenapadá, jak to udělat chytře. A hlavně vybrat z databáze WHERE response_id IN (100 hodnot jako 1,8,20, …) ???

Díky za rady

Editoval Jack06 (14. 4. 2012 16:33)

LeonardoCA
Člen | 296
+
0
-

Lze to vyřešit např. takto:

SELECT c.response_id, n.`text` FROM
(
	SELECT a.response_id
	FROM `names` a
	JOIN `names` b ON a.response_id = b.response_id AND b.`text` = 'pepa'
	WHERE a.`text` = 'honza'
	GROUP BY a.response_id
	ORDER BY a.response_id ASC
	LIMIT 0,10
) c
JOIN `names` n ON n.response_id = c.response_id
ORDER BY c.response_id ASC, n.`text` ASC

Vnitřní select

  • získá response_id pro které platí podmínka
  • vytváří temporary table, proto pokud by šlo o velké množství dat, řazení a limit musí být už ve vnitřním selectu, ať se nevytváří zbytečně obrovská temporary table ze všech dat

Vnější select

  • pak pouze pomocí JOIN získá všechny záznamy
  • řadit se musí znovu i podle response_id

Pro malé tabulky s pár tisíc řádky by to mělo fungovat svižně.
Při velkém počtu záznamů /stovky tisíc nebo miliony/ by se případně muselo hledat jiné řešení.

Editoval LeonardoCA (15. 4. 2012 3:17)

Jack06
Člen | 168
+
0
-

Tady právěty podmínky, že to musí být honza a pepa, jsou je ukázkové. Těch podmínek může být třeba 20 a vytvářejí se dynamicky

petr.pavel
Člen | 535
+
0
-
select response_id
from aaa
where `text` = 'pepa' or `text` = 'honza'
group by response_id
having count(*) = 2