rid*_*ack 8 mysql sql join subquery
我创建了2个可以使用相同功能的查询.它们都包含我想要合并到单个查询中的属性,但我无法做到.
QUERY 1 - 给我我想要的结果.慢(~0.700秒)
QUERY 2 - 给了我很多我忽略并跳过的行.快(~0.005秒)
我的目标是修改QUERY 2以删除除每个项目1之外的所有空价格行.我似乎无法做到这一点,而不是在表现上喋喋不休.这是由于我缺乏对MySQL中索引使用的经验和理解.
查询1
使用设计不佳的子查询,该子查询不允许在包含10k行的tbl_sale(e)中使用索引.
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
Run Code Online (Sandbox Code Playgroud)
这是EXPLAIN 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
Run Code Online (Sandbox Code Playgroud)
查询2
使用非常有效的所有左连接(ORDER BY除外).索引用于每个连接.此查询返回tbl_watch中每个项目的所有可能匹配项.这是查询:
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
Run Code Online (Sandbox Code Playgroud)
以下是查询的EXPLAIN:
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
Run Code Online (Sandbox Code Playgroud)
如何修改QUERY 2(更高效)以便在QUERY 1中使用我需要的行?
谢谢迈克
查询 1 中的子选择使用隐式内部联接,而查询 2 使用所有左联接显式联接。因此,没有 where 子句可以排除查询 2 中的数据。我会取出几行中的 LEFT(如标记的那样),看看这如何改进:
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 removed below
JOIN tbl_storeflyer AS d ON d.store_id = c.store_id
AND d.date_beg = '$s_date'
-- Left removed below
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`
Run Code Online (Sandbox Code Playgroud)
您还可以考虑从连接中取出 and 子句并将它们移动到 WHERE:
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'
JOIN tbl_storeflyer AS d ON d.store_id = c.store_id
JOIN tbl_sale AS e ON e.item_id = a.item_id
LEFT JOIN tbl_store as f ON d.store_id = f.id
WHERE a.user_id = '$user_id'
AND d.date_beg = '$s_date'
AND e.flyer_id = d.flyer_id
ORDER BY b.description ASC
Run Code Online (Sandbox Code Playgroud)
最后,日期数学相当密集。在查询 2 中,使用外连接,您可以避免很多连接,但您可能需要它。我尝试使用子查询来获取 ids 并进行限制:
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'
JOIN tbl_storeflyer AS d ON d.store_id = c.store_id
JOIN tbl_sale AS e ON e.item_id = a.item_id
LEFT JOIN tbl_store as f ON d.store_id = f.id
WHERE a.user_id = '$user_id'
AND e.flyer_id = d.flyer_id
AND d.id in (select d.id from d where date_beg = '$s_date')
ORDER BY b.description ASC
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1748 次 |
| 最近记录: |