具有大量数据的多个连接的 MySql 查询
Posted
技术标签:
【中文标题】具有大量数据的多个连接的 MySql 查询【英文标题】:MySql Query with multiple joins with huge data 【发布时间】:2019-06-10 09:06:07 【问题描述】:我在一个数据库中有三个表
表 feedback_responses
resp_id(Primary) | name | mobile | pnr | message | added_on
表 feedback_response_items
feed_item_id | resp_id | qn_id | ans_id
表 feedback_answers
ans_id(Primary) | ans_desc | qn_id
我想要显示 feedback_responses 表 中的所有行,并且每行包含 feedback_response_items 中与表 feedback_responses 的主键匹配的 9 个项目这是 resp_id
所以我会得到所有问题的ans_id,我会得到表feedback_answers
中响应的答案描述查询是
$f=$db->Query("
SELECT fr.resp_id, fr.name, fr.mobile, fr.pnr, fr.message,
(SELECT ans_id FROM feedback_response_items fr1 WHERE fr.resp_id = fr1.resp_id AND fr1.qn_id='1') AS qn1Ans,
(SELECT ans_id FROM feedback_response_items fr2 WHERE fr.resp_id = fr2.resp_id AND fr2.qn_id='2') AS qn2Ans,
(SELECT ans_id FROM feedback_response_items fr3 WHERE fr.resp_id = fr3.resp_id AND fr3.qn_id='3') AS qn3Ans,
(SELECT ans_id FROM feedback_response_items fr4 WHERE fr.resp_id = fr4.resp_id AND fr4.qn_id='4') AS qn4Ans,
(SELECT ans_id FROM feedback_response_items fr5 WHERE fr.resp_id = fr5.resp_id AND fr5.qn_id='5') AS qn5Ans,
(SELECT ans_id FROM feedback_response_items fr6 WHERE fr.resp_id = fr6.resp_id AND fr6.qn_id='6') AS qn6Ans,
(SELECT ans_id FROM feedback_response_items fr7 WHERE fr.resp_id = fr7.resp_id AND fr7.qn_id='7') AS qn7Ans,
(SELECT ans_id FROM feedback_response_items fr8 WHERE fr.resp_id = fr8.resp_id AND fr8.qn_id='8') AS qn8Ans,
(SELECT ans_id FROM feedback_response_items fr10 WHERE fr.resp_id = fr10.resp_id AND fr10.qn_id='10') AS qn10Ans
FROM feedback_responses fr
");
上面的查询需要很多时间(超过 2 分钟)来执行如何优化它,我对此感到震惊,任何反馈都将非常感激。
【问题讨论】:
顺便说一句,您可以通过命名列 response_id、answer_id 等来拯救追随您的可怜的管理员。 【参考方案1】:我认为,如果您在 select 语句中移动子查询,并 JOIN 项目表,您的查询将运行得非常快! (似乎子查询对每一行都执行,所以需要时间)。这将起作用:
SELECT fr.resp_id, fr.name, fr.mobile, fr.pnr, fr.message,
MAX(IF(fri.qn_id='1',ans_id,0)) AS qn1Ans,
MAX(IF(fri.qn_id='2',ans_id,0)) AS qn2Ans,
MAX(IF(fri.qn_id='3',ans_id,0)) AS qn3Ans,
MAX(IF(fri.qn_id='4',ans_id,0)) AS qn4Ans,
MAX(IF(fri.qn_id='5',ans_id,0)) AS qn5Ans,
MAX(IF(fri.qn_id='6',ans_id,0)) AS qn6Ans,
MAX(IF(fri.qn_id='7',ans_id,0)) AS qn7Ans,
MAX(IF(fri.qn_id='8',ans_id,0)) AS qn8Ans,
MAX(IF(fri.qn_id='10',ans_id,0)) AS qn10Ans,
FROM feedback_responses fr
JOIN feedback_response_items fri ON fr.resp_id = fri.resp_id
GROUP BY fr.resp_id, fr.name, fr.mobile, fr.pnr, fr.message
希望对你有帮助!
【讨论】:
【参考方案2】:这可能不是一个让您完全满意的答案,因为可能需要一些编程:
您忽略了指定为各种表指定的索引。对于表 feedback_response_items,您应该至少在列 resp_id 上定义了一个索引(并且在 qn_id 上的一个索引可能不会有任何影响)。如果没有,请这样做,看看如何减少执行时间。
如果您已经定义了索引或定义索引并没有显着提高执行时间,则需要进行一些编程。您的 SQL 应该是:
SELECT fr.resp_id, fr.name, fr.mobile, fr.pnr, fr.message, fri.ans_id /*, fa.ans_desc */
FROM feedback_responses fr
JOIN feedback_response_items fri ON fr.resp_id = fri.resp_id
AND fri.qn_id IN ('1','2','3','4','5','6','7','8','10')
/* JOIN feedback_answers fa on fri.ans_id = fa.ans_id */
ORDER BY fri.qn_id
;
删除上述 SQL 中的 cmets 以检索答案。现在对于 fr.resp_id 的每个值,将返回 9 行。目的是让这个 SQL 由一个计算机程序发出,该程序将处理 9 行的组并根据需要显示结果。
【讨论】:
以上是关于具有大量数据的多个连接的 MySql 查询的主要内容,如果未能解决你的问题,请参考以下文章