Left Join on Subquery with criteria in MySQL alternative?
SELECT a.tag,CONCAT(u.first_name,' ',u.last_name)
FROM assets a
LEFT JOIN (SELECT asset_id,assigned_to_id
FROM asset_activity
WHERE assigned IN (SELECT MAX(assigned)
FROM asset_activity
GROUP BY asset_id))
v ON v.asset_id = a.id
LEFT JOIN users u ON v.assigned_to_id = u.id
WHERE ($1 IS NULL OR u.last_name LIKE $1)
Since MySQL performs horribly with left joins on a subquery, I need to find some other method to do this. I can select what I need with subqueries within the select, but it needs to be conditional. It should only return the records that match the LIKE, and with subqueries, it would still return a record from assets with a null value for assigned_to, so I can't do that.
EXECUTION PLAN:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL null null null null 1,447
1 PRIMARY <derived2> ALL null null null null 1,396
1 PRIMARY u eq_ref PRIMARY PRIMARY 4 v.assigned_to_id 1
2 DERIVED asset_activity ALL null null null null 1,400 Using where
3 DEPENDENT SUBQUERY asset_activity开发者_JAVA技巧 index null asset_id 4 null 1,400 Using filesort
INDEXES:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
assets 0 PRIMARY 1 id A 144 "" BTREE ""
assets 1 serial 1 serial A 1447 YES BTREE ""
assets 1 serial 2 cal_num A 1447 YES BTREE ""
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
asset_activity 0 PRIMARY 1 id A 1400 "" BTREE ""
asset_activity 1 asset_id 1 asset_id A "" BTREE ""
asset_activity 1 location_id 1 location_id A YES BTREE ""
asset_activity 1 assigned_to_id 1 assigned_to_id A YES BTREE ""
asset_activity 1 assigned_to_table 1 assigned_to_table A YES BTREE ""
asset_activity 1 created 1 created A "" BTREE ""
OK, here's how I finally got it performing:
SELECT a.tag,CONCAT(u.first_name,' ',u.last_name)
FROM assets a
LEFT JOIN asset_activity v ON v.asset_id = a.id
LEFT JOIN asset_activity v2 ON v2.asset_id = a.id
AND (v.assigned < v2.assigned OR v.assigned = v2.assigned AND v.id < v2.id)
LEFT JOIN users u ON v.assigned_to_id = u.id
WHERE v2.id IS NULL
AND ($1 IS NULL OR u.last_name LIKE $1)
This performs far better than the left join on a subquery with a subquery. .0064 sec as compared to 5 sec or more for the other method and it turned into more when binding it to a grid in my code, for paging, etc.
精彩评论