Ongelooflijk trage queries met ZF
Mooi, en nu nog die 15 overbodige queries eruit ;-)
Erwin, toch een probleem. Hij pakt de prop_value niet helemaal zoals het moet zijn. Er zijn twee mogelijkheden bij beide, = of !=. Maakt niet uit wat ik doe, hij pakt geen van de twee?
Lijkt wel alsof ik 'm nog een keer moet herhalen in de WHERE?
Een join is niks meer dan twee (of meerdere) tabellen combineren tot één tabel (onder bepaalde voorwaarden)
Dus als je
Krijg je dit soort resultaat:
Hierop moet je dus kunnen filteren in de WHERE
Gewijzigd op 24/07/2012 20:49:38 door Ger van Steenderen
Ger, de query die Erwin mij gaf, deed die WHERE al in de JOIN, moet ik die dan nogmaals herhalen onderaan? Dacht juist dat dmv deze JOIN, dat niet meer hoefde!
Chris op 24/07/2012 20:09:32:
Erwin, toch een probleem. Hij pakt de prop_value niet helemaal zoals het moet zijn. Er zijn twee mogelijkheden bij beide, = of !=. Maakt niet uit wat ik doe, hij pakt geen van de twee?
Lijkt wel alsof ik 'm nog een keer moet herhalen in de WHERE?
Lijkt wel alsof ik 'm nog een keer moet herhalen in de WHERE?
Ik begrijp niet helemaal wat je hiermee bedoelt. Wat gaat er niet goed dan?
Herhalen in de WHERE zou niet moeten, want records die niet aan de join voorwaarde voldoen zullen niet worden opgenomen in de dataset.
Dat lijkt dus niet te werken, die INNER JOIN pakt niet de juiste velden. De vergelijking, = of != maakt niet uit, hij pakt niet de juiste waarde(?) Vandaar de vraag of het nog moest worden herhaald
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
SELECT ....
FROM table1
LEFT JOIN table2 ON ....
LEFT JOIN ....
INNER JOIN ....
WHERE (
(
tabel1.is_online = 1
AND
tabel2.calendar_date = :calendardate
)
FROM table1
LEFT JOIN table2 ON ....
LEFT JOIN ....
INNER JOIN ....
WHERE (
(
tabel1.is_online = 1
AND
tabel2.calendar_date = :calendardate
)
Door die laatste INNER JOIN worden de voorgaande LEFT JOINs ook INNER JOINs
Ook vergelijk je tabel2.calendar_date met een bepaalde waarde dus heeft die LEFT JOIN geen zin.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT
tabel1.id, tabel1.always_open, COUNT(*), --[enderest]
FROM
tabel1
LEFT JOIN
tabel2 ON tabel1.id = tabel2.tabel1_id
LEFT JOIN
tabel1_properties AS tp ON tabel1.id = tabel1_properties.tabel1_id
WHERE (
(tabel1.is_online = 1 AND tabel2.calendar_date = :calendardate)
OR
( tabel1.is_online = 1 AND tabel1.always_open = 1)
)
AND (
(tp.prop_name = 'kenmerk1' AND tp.prop_value BETWEEN :kenmerk1_1 AND :kenmerk1_2)
OR
(tp.prop_name = 'kenmerk2' AND tp.prop_value != :kenmerk2)
OR
(tp.prop_name = 'kenmerk3' AND tp.prop_value != :kenmerk3)
)
GROUP BY table1.id HAVING (COUNT(*) = 3)
ORDER BY tabel1.id
tabel1.id, tabel1.always_open, COUNT(*), --[enderest]
FROM
tabel1
LEFT JOIN
tabel2 ON tabel1.id = tabel2.tabel1_id
LEFT JOIN
tabel1_properties AS tp ON tabel1.id = tabel1_properties.tabel1_id
WHERE (
(tabel1.is_online = 1 AND tabel2.calendar_date = :calendardate)
OR
( tabel1.is_online = 1 AND tabel1.always_open = 1)
)
AND (
(tp.prop_name = 'kenmerk1' AND tp.prop_value BETWEEN :kenmerk1_1 AND :kenmerk1_2)
OR
(tp.prop_name = 'kenmerk2' AND tp.prop_value != :kenmerk2)
OR
(tp.prop_name = 'kenmerk3' AND tp.prop_value != :kenmerk3)
)
GROUP BY table1.id HAVING (COUNT(*) = 3)
ORDER BY tabel1.id
Ah, foutje in mijn voorbeeld dus. De laatste INNER JOIN moet ook gewoon een LEFT JOIN zijn, dan zou het wel moeten werken.
Denk het niet, want dan hebben die JOIN voorwaarden geen effect op de selectie en moet je ze alsnog in de WHERE zetten
Overigens komt dit vrijwel overheen met wat ik in eerste instantie had. Die is vrij snel voor weinig resultaten, maar bij 10.000+ wordt hij een stuk trager
Ger van Steenderen op 25/07/2012 11:49:12:
Denk het niet, want dan hebben die JOIN voorwaarden geen effect op de selectie en moet je ze alsnog in de WHERE zetten
Hmm, heb ik me dan helemaal vergist en moeten het allemaal INNER JOINs zijn in plaats van LEFT JOINs. Chris, kan je dat eens proberen. Zet daarbij een DISTINCT in je select statement en dan zou het moeten werken (volgens mijn beperkte test mogelijkheid). Alleen of het nog steeds zo snel is is dan even de vraag...
Helaas Erwin, met INNER's laat hij helemaal niets meer zien.. :(
Zo op afstand wordt het natuurlijk wel een beetje lastig om dan nog iets te kunnen doen, vooral omdat we de echte query niet kunnen zien. Zo ver als ik het kan testen werkt het. Als je dus geen andere fout ergens kunt vinden kan ik je vrees ik niet veel verder helpen.
@Chris
Als je nu die tabel2 eens buiten beschouwing laat?
Geen verschil
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
SELECT
t1.id, t1.always_open, t1.is_online
FROM (
SELECT
tabel1.id, tabel1.always_open
FROM
tabel1
INNER JOIN
tabel1_properties AS tp1
ON (
tabel1.id = tp1.tabel1_id
AND tp1.prop_name = 'kenmerk1'
AND tp1.prop_value
BETWEEN :kenmerk1_1
AND :kenmerk1_2
)
INNER JOIN
tabel1_properties AS tp2
ON (
tabel1.id = tp2.tabel1_id
AND tp2.prop_name = 'kenmerk2'
AND tp2.prop_value != :kenmerk2
)
INNER JOIN
tabel1_properties AS tp3
ON (
tabel1.id = tp3.tabel1_id
AND tp3.prop_name = 'kenmerk3'
AND tp3.prop_value != :kenmerk3
)
) AS t1
LEFT JOIN
tabel2
ON
t1.id = tabel2.table1_id
WHERE (
t1.is_online = 1
AND
tabel2.calendar_date = :calendardate
)
OR (
t1.is_online = 1
AND
t1.always_open = 1
)
t1.id, t1.always_open, t1.is_online
FROM (
SELECT
tabel1.id, tabel1.always_open
FROM
tabel1
INNER JOIN
tabel1_properties AS tp1
ON (
tabel1.id = tp1.tabel1_id
AND tp1.prop_name = 'kenmerk1'
AND tp1.prop_value
BETWEEN :kenmerk1_1
AND :kenmerk1_2
)
INNER JOIN
tabel1_properties AS tp2
ON (
tabel1.id = tp2.tabel1_id
AND tp2.prop_name = 'kenmerk2'
AND tp2.prop_value != :kenmerk2
)
INNER JOIN
tabel1_properties AS tp3
ON (
tabel1.id = tp3.tabel1_id
AND tp3.prop_name = 'kenmerk3'
AND tp3.prop_value != :kenmerk3
)
) AS t1
LEFT JOIN
tabel2
ON
t1.id = tabel2.table1_id
WHERE (
t1.is_online = 1
AND
tabel2.calendar_date = :calendardate
)
OR (
t1.is_online = 1
AND
t1.always_open = 1
)
Dit zou in principe moeten werken, zo niet, dan gaat er denk iets mis met de parameters