I created 2 queries that I can use that perform the same function. They both contain properties that I would like to combine into a single request, but I could not.
QUERY 1 - Gives me exactly the results that I want. Slow (~ 0.7 sec)
QUERY 2 - Gives me a lot of lines that I ignore and skip. Fast (~ 0.005 sec)
My goal is to modify QUERY 2 to remove all zero price lines except 1 for each item. It seems that I canβt do this without rushing to the play. This is due to my lack of experience and understanding of using index in MySQL.
QUERY 1
Uses a poorly designed subquery that does not allow indexing via tbl_sale (e), which contains 10k lines.
SELECT b.id, b.sv, b.description, der.store_id, f.name, der.price FROM tbl_watch AS a LEFT JOIN tbl_item AS b ON a.item_id = b.id LEFT JOIN ( SELECT c.store_id, d.flyer_id, e.item_id, e.price FROM tbl_storewatch AS c, tbl_storeflyer AS d FORCE INDEX ( storebeg_ndx ) , tbl_sale AS e WHERE c.user_id = '$user_id' AND ( d.store_id = c.store_id AND d.date_beg = '20121206' ) AND e.flyer_id = d.flyer_id ) AS der ON a.item_id = der.item_id LEFT JOIN tbl_store as f ON der.store_id = f.id WHERE a.user_id = '$user_id' ORDER BY b.description ASC
Here is an EXPLAIN example for QUERY 1
id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY a ref user_item_ndx user_item_ndx 4 const 30 Using index; Using temporary; Using filesort 1 PRIMARY b eq_ref PRIMARY PRIMARY 4 a.item_id 1 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 300 1 PRIMARY f eq_ref PRIMARY PRIMARY 4 der.store_id 1 2 DERIVED c ref user_ndx user_ndx 4 6 2 DERIVED e ALL NULL NULL NULL NULL 9473 Using join buffer 2 DERIVED d eq_ref storebeg_ndx storebeg_ndx 8 c.store_id 1 Using where
QUERY 2
Uses all left joins that are very effective (except for ORDER BY). Indexes are used for each connection. This query returns all possible matches for each element in tbl_watch. Here is the request:
SELECT b.id, b.sv, b.description, c.store_id, f.name, e.price FROM tbl_watch AS a LEFT JOIN tbl_item AS b ON a.item_id = b.id LEFT JOIN tbl_storewatch AS c ON c.user_id = '$user_id' LEFT JOIN tbl_storeflyer AS d ON d.store_id = c.store_id AND d.date_beg = '$s_date' LEFT JOIN tbl_sale AS e ON e.item_id = a.item_id AND e.flyer_id = d.flyer_id LEFT JOIN tbl_store as f ON d.store_id = f.id WHERE a.user_id = '$user_id' ORDER BY b.description ASC
Here is an EXPLAIN example for a query:
id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE a ref user_item_ndx user_item_ndx 4 const 6 Using index; Using temporary; Using filesort 1 SIMPLE b eq_ref PRIMARY PRIMARY 4 a.item_id 1 1 SIMPLE c ref user_ndx user_ndx 4 const 2 1 SIMPLE d eq_ref storebeg_ndx,storendx storebeg_ndx 8 c.store_id,const 1 1 SIMPLE e eq_ref itemflyer_ndx itemflyer_ndx 8 a.item_id,d.flyer_id 1 1 SIMPLE f eq_ref PRIMARY PRIMARY 4 d.store_id 1
How can I modify QUERY 2 (more efficiently) to give me only the rows I need in QUERY 1 to work with?
Thanks Mike