我正在使用MySQL 5.6.17
。
我有table
包含标题的主条目,让我们说出Master_titles
。它包含列id int primary key auto-increment
,title varchar(255)
。数据如下所示:
id title
1 Item one
2 Item two
3 Item three
4 Item five
6 Item six
7 Item seven
8 Item eight
9 Item nine
10 Item ten
另一个名为routines
的表self-referencing table
包含records with parent-child relationship
。列是id int primary key auto-increment
,master_title_id int foreign key references id of Master_titles
,type varchar(2)
,parent int foreign key referencing id of routines
本身。数据如下:
id master_title_id type parent
1 1 G null
2 2 Q 1
3 3 A 2
4 4 A 2
5 5 Q 1
6 6 A 5
7 8 A 5
8 2 G null
9 5 Q 8
10 7 A 9
11 8 A 9
12 9 A 9
另一张表让我们说data
,其中包含id int primary key auto-increment
,routine_id int foreign key references id of routines
,group id int
,question_id int
,answer id int
等列。此处,列的所有记录,即group_id
,question_id
,answer_id
将是id
表的routines
。数据如下:
id routine_id group_id question_id answer_id
1 2 1 2 4
2 5 1 5 6
3 9 8 9 11
4 5 1 5 7
5 2 1 2 7
3 9 8 9 10
现在,我想要query
从titles
表中为group_id
,question_id
和answer_id
列提取master_titles
。
我可以使用sub-query
来做,但是什么是最有效的方法来获取记录而没有开销?
查询即工作但我不喜欢使用如下:
SELECT data.created_at,
(SELECT Master_titles.title FROM `Master_titles` LEFT JOIN routines ON Master_titles.id = routines.master_title_id LEFT JOIN data ON routines.id = data.group_id WHERE data.id = data.`id`) AS Group,
(SELECT Master_titles.title FROM `Master_titles` LEFT JOIN routines ON Master_titles.id = routines.master_title_id LEFT JOIN data ON routines.id = data.question_id WHERE data.id = data.`id`) AS Question,
(SELECT Master_titles.title FROM `Master_titles` LEFT JOIN routines ON Master_titles.id = routines.master_title_id LEFT JOIN data ON routines.id = data.answer_id WHERE data.id = data.`id`) AS Answer
FROM data;
答案 0 :(得分:2)
根据您的评论说明,表data
中包含ID的所有列实际上都是ids
routines
表,您需要通过执行连接来获取每列的标题路径为routines > master_titles
。
SELECT
d.id,
d.routine_id,
mgroup.title group,
mquestion.title question,
manswer.title answer
FROM
data d
LEFT JOIN routines r1 ON ( d.group_id = r.id )
LEFT JOIN master_titles mgroup ON ( r1.master_title_id = m.id )
LEFT JOIN routines r2 ON ( d.question_id = r.id )
LEFT JOIN master_titles mquestion ON ( r2.master_title_id = m.id )
LEFT JOIN routines r3 ON ( d.answer_id = r.id )
LEFT JOIN master_titles manswer ON ( r3.master_title_id = m.id )
不要担心连接数量(从不按行数计算查询成本)。
我建议跟随索引来加速:例程(master_title_id)。
另外,在group_id,question_id和answer_id列上考虑(无法估计您的环境)索引。
你最了解它是否能帮助你提高性能,同时不会无利可图地损害你的写作/空间。
答案 1 :(得分:1)
从“考虑我”回答中稍作改动。
SELECT
d.id,
d.routine_id,
mgroup.title group,
mquestion.title question,
manswer.title answer
FROM
data d
JOIN routines r1 ON ( d.group_id = r.id )
JOIN master_titles mgroup ON ( r1.master_title_id = m.id )
JOIN routines r2 ON ( d.question_id = r.id )
JOIN master_titles mquestion ON ( r2.master_title_id = m.id )
JOIN routines r3 ON ( d.answer_id = r.id )
JOIN master_titles manswer ON ( r3.master_title_id = m.id )
内部联接应该更好,因为group_id
,question_id
和answer_id
未在data
表中定义为可空。但由于没有外键关系,如果在例程表中没有值,则可能存在缺少行的实例。
答案 2 :(得分:-1)
您可以通过对正在连接的表进行别名来对同一个表执行多个连接。
SELECT data.id, gm.title AS gm_title, qm.title AS qm_title, am.title AS am_title
JOIN routines AS gr
ON gr.id = data.group_id
JOIN master_titles AS gm
ON gm.id = gr.master_title_id
JOIN routines AS qr
ON qr.id = data.question_id
JOIN master_titles AS qm
ON qm.id = qr.master_title_id
JOIN routines AS ar
ON ar.id = data.answer_id
JOIN master_titles AS am
ON am.id = ar.master_title_id
FROM data