问题
I spent some time trying to get working this SELECT with CASE but I failed... (thank to that I'm using COLASCE() now)
How could I optimize this SELECT by using CASE/IF sentences? Is this a fast way to query from different tables selected by a field?
SELECT a.folderid, a.foldername, a.contenttype, COALESCE(b.descriptor, c.descriptor, d.descriptor, e.descriptor, f.descriptor) as descriptor
FROM t_folders a
LEFT JOIN t_files b
ON a.contenttype = 'file' AND a.contentid = b.fileid
LEFT JOIN t_links c
ON a.contenttype = 'link' AND a.contentid = c.linkid
LEFT JOIN t_extfiles d
ON a.contenttype = 'extfile' AND a.contentid = d.extfileid
LEFT JOIN t_videos e
ON a.contenttype = 'video' AND a.contentid = e.videoid
LEFT JOIN t_exams f
ON a.contenttype = 'exam' AND a.contentid = f.examid
WHERE a.folderid = $folderId
ORDER BY a.folderid DESC
回答1:
Using case statement will not make the query faster in your case, but since you asked for it, below is how it would look like.
SELECT a.folderid, a.foldername, a.contenttype,
(CASE a.contenttype
WHEN 'file' THEN b.descriptor
WHEN 'link' THEN c.descriptor
WHEN 'extfile' THEN d.descriptor
WHEN 'video' THEN e.descriptor
ELSE f.descriptor
END CASE) AS descriptor
FROM t_folders a
LEFT JOIN t_files b ON a.contenttype = 'file' AND a.contentid = b.fileid
LEFT JOIN t_links c ON a.contenttype = 'link' AND a.contentid = c.linkid
LEFT JOIN t_extfiles d ON a.contenttype = 'extfile' AND a.contentid = d.extfileid
LEFT JOIN t_videos e ON a.contenttype = 'video' AND a.contentid = e.videoid
LEFT JOIN t_exams f ON a.contenttype = 'exam' AND a.contentid = f.examid
WHERE a.folderid = $folderId
ORDER BY a.folderid DESC
If each of the t_files, t_links, etc tables has the folder_id field, I would also try doing a UNION on these tables and then left join the result with t_folders to get the folderid and foldername.
回答2:
The joins have to be done this way because the come out of different tables. You cannot use CASE to switch which table a query is coming out of: the statement has to be parsed, including its data sources, before there are values to compare.
More to the point, CASE returns values, whereas table names are.. I don't know the technical term.. structural components of the query. It's sort of the same reason you can't select out of table "Cool_Stuff" with:
select * from "Cool_" + "Stuff"
Hope this answers your question!
回答3:
You may do the following
select master.* , COALESCE(b.descriptor, c.descriptor, d.descriptor, e.descriptor, f.descriptor) as descriptor
from
( SELECT a.folderid, a.foldername, a.contenttype
FROM t_folders a
WHERE a.folderid = $folderId
ORDER BY a.folderid DESC ) master
LEFT JOIN t_files b
ON master.contenttype = 'file' AND master.contentid = b.fileid
LEFT JOIN t_links c
ON master.contenttype = 'link' AND master.contentid = c.linkid
LEFT JOIN t_extfiles d
ON master.contenttype = 'extfile' AND master.contentid = d.extfileid
LEFT JOIN t_videos e
ON master.contenttype = 'video' AND master.contentid = e.videoid
LEFT JOIN t_exams f
ON master.contenttype = 'exam' AND master.contentid = f.examid
While minimizing the result on table a, the joins operation can be optmizsed
来源:https://stackoverflow.com/questions/9749986/mysql-left-join-optimization-with-case