MySQL: Először szűrni és az eredményt JOIN-olni, howto?
Van egy főtábla (`employees`
):
emp_no int(11)
birth_date date
first_name varchar(14)
last_name varchar(16)
gender enum('M','F')
hire_date date
Egy segédtábla (`titles`
):
emp_no int(11)
title varchar(50)
from_date date
to_date date NULL
És egy másik segédtábla (`salaries`
):
emp_no int(11)
salary int(11)
from_date date
to_date date
Mind a két segédtáblában foreign key az `emp_no`
. A szűrés és lekérdezés megy így is:
SELECT `employees`.*, `titles`.`title`, `salaries`.`salary`
FROM `employees`
LEFT JOIN `titles` ON
(`titles`.`emp_no` = `employees`.`emp_no`) AND
(`titles`.`from_date` = (SELECT MAX(`from_date`) FROM `titles` WHERE `titles`.`emp_no` = `employees`.`emp_no`))
LEFT JOIN `salaries` ON
(`salaries`.`emp_no` = `employees`.`emp_no`) AND
(`salaries`.`from_date` = (SELECT MAX(`from_date`) FROM `salaries` WHERE `salaries`.`emp_no` = `employees`.`emp_no`))
WHERE (`titles`.`title`='Staff') AND (`salaries`.`salary`>='120000')
LIMIT 0, 20
De ez így nagyon lassú, 4-5 másodperceket kotorászik, pedig alig hárommillió rekord van a `salaries`
-ben, négyszázezer a `titles`
-ben és háromszázezer az `employees`
-ben. (Ha pedig még sorrendezés is kerül bele, akkor aztán több, mint 10 másodperc...)
Próbáltam így is
SELECT `employees`.*, `titles`.`title`, `salaries`.`salary`
FROM `employees`
LEFT JOIN `titles` ON
(`titles`.`emp_no` = `employees`.`emp_no`) AND
(`titles`.`from_date` = (SELECT MAX(`from_date`) FROM `titles` WHERE `titles`.`emp_no` = `employees`.`emp_no`))
LEFT JOIN `salaries` ON
(`salaries`.`emp_no` = `employees`.`emp_no`) AND
(`salaries`.`from_date` = (SELECT MAX(`from_date`) FROM `salaries` WHERE `salaries`.`emp_no` = `employees`.`emp_no`))
WHERE `employees`.`emp_no` IN
(
SELECT `ut`.`emp_no` FROM
(
(SELECT `titles`.`emp_no` FROM `titles` WHERE `titles`.`title`='Staff')
UNION
(SELECT `salaries`.`emp_no` FROM `salaries` WHERE `salaries`.`salary`>='100000')
) `ut`
)
LIMIT 0, 20
viszont így nem jó a végeredmény, rossz értékek jelennek meg a szűrt oszlopokban. Próbáltam úgy is, hogy először megszűröm az eredményt és aztán JOIN-olok
SELECT `employees`.*, `titles`.`title`, `salaries`.`salary` FROM
(
SELECT * FROM `employees`
WHERE `employees`.`emp_no` IN
(
SELECT `ut`.`emp_no` FROM
(
(SELECT `titles`.`emp_no` FROM `titles` WHERE `titles`.`title`='Staff')
UNION
(SELECT `salaries`.`emp_no` FROM `salaries` WHERE `salaries`.`salary`>='100000')
) `ut`
)
) AS `employees`
LEFT JOIN `titles` ON
(`titles`.`emp_no` = `employees`.`emp_no`) AND
(`titles`.`from_date` = (SELECT MAX(`from_date`) FROM `titles` WHERE `titles`.`emp_no` = `employees`.`emp_no`))
LEFT JOIN `salaries` ON
(`salaries`.`emp_no` = `employees`.`emp_no`) AND
(`salaries`.`from_date` = (SELECT MAX(`from_date`) FROM `salaries` WHERE `salaries`.`emp_no` = `employees`.`emp_no`))
LIMIT 0, 20
de dettó rossz adatok jöttek ki.
Sajnos már vagy 8-10 év óta nem foglalkoztam SQL-lel a sima SELECT
/INSERT
/UPDATE
/DELETE
szinten túl, így keresni is hiába kerestem, mert igazából nem tudom, hogy mit keressek.
Hogyan lehet ezt tisztességesen megcsinálni, hogy előbb leválogatja a két segédtáblából azokat a sorokat, amik érintettek és csak azokat kérje le a főtáblából, amik csatolhatóak?
- Tovább (MySQL: Először szűrni és az eredményt JOIN-olni, howto?)
- 1337 megtekintés