views:

43

answers:

1

Hello everyone,

I have a complex SQL query with nested 'subqueries' that I want to optimize

    SELECT
'likes' `type`,
entry_date item_date,
CASE `type`
    WHEN 'entry_id' THEN entry_id
    WHEN 'member_id' THEN f.member_id
    WHEN 'topic_id' THEN entry_id
END    
AS item_id,
CASE `type`
    WHEN 'entry_id' THEN (SELECT title FROM exp_weblog_titles WHERE entry_id=item_id)
    WHEN 'member_id' THEN (SELECT screen_name FROM exp_members WHERE member_id=item_id)
    WHEN 'topic_id' THEN (SELECT title FROM exp_forum_topics WHERE topic_id=item_id)
END    
AS item_title,
CASE `type`
    WHEN 'member_id' THEN (SELECT username FROM exp_members WHERE member_id=item_id)
    ELSE ''
END    
AS  item_url_title,
f.type parent_type,
CASE `type`
    WHEN 'entry_id' THEN (SELECT weblog_id FROM exp_weblog_titles WHERE entry_id=item_id)
    WHEN 'member_id' THEN ''
    WHEN 'topic_id' THEN (SELECT forum_id FROM exp_forum_topics WHERE topic_id=item_id)
END    
AS parent_id,
CASE `type`
    WHEN 'entry_id' THEN ''
    WHEN 'member_id' THEN ''
    WHEN 'topic_id' THEN (SELECT forum_name FROM exp_forums WHERE forum_id=parent_id)
END    
AS parent_title,         
m.member_id actor_member_id,
screen_name actor_screen_name,
username actor_username,
photo_filename actor_photo,
avatar_filename actor_avatar
FROM exp_favorites f, exp_members m
WHERE f.member_id=m.member_id

As you can notice, in subqueries some table are queried several times for the same row but a different field.
Like, I have

SELECT screen_name FROM exp_members WHERE member_id=item_id  

and

SELECT username FROM exp_members WHERE member_id=item_id  

which I'd live to see combined to mimize the number of reuests and server load.

Is there a way to do this? Any advices?

UPD. table structure is following:
CREATE TABLE exp_favorites (
favorites_id int(10) unsigned NOT NULL auto_increment,
type varchar(16) NOT NULL default 'entry_id',
author_id int(10) unsigned NOT NULL default '0',
entry_id int(10) unsigned NOT NULL,
member_id int(10) unsigned NOT NULL,
site_id smallint(3) unsigned NOT NULL default '1',
entry_date int(10) unsigned NOT NULL,
notes text NOT NULL,
public char(1) NOT NULL default 'y',
PRIMARY KEY (favorites_id),
KEY author_id (author_id),
KEY entry_id (entry_id),
KEY member_id (member_id),
KEY site_id (site_id),
KEY public (public),
KEY type (type)
)

+1  A: 

You can do something like this:

SELECT
'likes' `type`,
entry_date item_date,
CASE `type`
    WHEN 'entry_id' THEN entry_id
    WHEN 'member_id' THEN f.member_id
    WHEN 'topic_id' THEN entry_id
END    
AS item_id,
CASE `type`
    WHEN 'entry_id' THEN wt.title
    WHEN 'member_id' THEN m2.screen_name
    WHEN 'topic_id' THEN ft.title
END    
AS item_title,
...
FROM exp_favorites f
inner join exp_members m ON f.member_id=m.member_id
left outer join exp_weblog_titles wt on wt.entry_id=f.item_id
left outer join exp_members m2 on m2.entry_id=f.item_id
left outer join exp_forum_topics ft on ft.entry_id=f.item_id
RedFilter
it does not look as option as f.item_id can relate to record in any of 3 tables, and thus the join will become just huge. Or am I wrong here?
runner
@runner: look at the join conditions in the last three table joins - all of them are from f.item_id, to the appropriate field in each table.
Mark Bannister
@RedFilter, I think a couple of those left joins need to be tweaked - exp_members is only ever joined to on member_id, so there is no need for m2, while forum topic is joined to on topic_id and parent_id but not entry_id.
Mark Bannister
@Mark: yeah there are likely so inaccuracies; without seeing a full schema I am not going to spend any more time on this - I think the concept is clear enough.
RedFilter
the problem is that f.item_id can refer to row in any of 3 tables (I use 'type' field todetermine what data needs to be used). So I think the join here might grow enourmously. Anyway, I'll try this solution and will see whether it's better then what I use or not.
runner
just as I expected - the query with joins takes more time to run. Will stick to sub-select for now. Thank you for advices, everyone!
runner