我在MySQL中使用UNION,以便将两个单独查询的结果汇总在一起。 这两个查询使用了很多相同的表。无论如何都要利用这个来优化查询?
SELECT 2 AS RELEVANCE_SCORE_TYPE,
VIEWER_ID,
QUESTION_ID,
sum(ANSWER_SCORE) AS RELEVANCE_SCORE
FROM(SELECT cr.COMMUNICATIONS_ID AS ANSWER_ID,
cr.CONSUMER_ID as VIEWER_ID,
nc.PARENT_COMMUNICATIONS_ID AS QUESTION_ID,
case when cr.CONSUMER_ID= nc.SENDER_CONSUMER_ID then 3*((24/(((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(cal.LAST_MOD_TIME)+3600)/3600))*(ces.EXPERT_SCORE * cirm.CONSUMER_RATING) + (12.5 * scs.SIMILARITY)* (1 - EXP(-0.5 * (cal.TIPS_AMOUNT / ATV.AVG_TIPS)) + .15)))
else ((24/(((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(cal.LAST_MOD_TIME)+3600)/3600))*(ces.EXPERT_SCORE * cirm.CONSUMER_RATING) + (12.5 * scs.SIMILARITY)* (1 - EXP(-0.5 * (cal.TIPS_AMOUNT / ATV.AVG_TIPS)) + .15)))
end as ANSWER_SCORE
FROM (SELECT 238 AS CONSUMER_ID,
ACTION_LOG_ID,
COMMUNICATIONS_ID
FROM consumer_action_log
WHERE COMM_TYPE_ID=4) AS cr
JOIN network_communications AS nc
ON cr.COMMUNICATIONS_ID=nc.COMMUNICATIONS_ID
JOIN consumer_action_log AS cal
ON cr.ACTION_LOG_ID=cal.ACTION_LOG_ID
JOIN communication_interest_mapping AS cim
ON nc.PARENT_COMMUNICATIONS_ID=cim.COMMUNICATION_ID
JOIN consumer_interest_rating_mapping AS cirm
ON cr.CONSUMER_ID=cirm.CONSUMER_ID
AND cim.CONSUMER_INTEREST_EXPERT_ID=cirm.CONSUMER_INTEREST_ID
JOIN consumer_expert_score AS ces
ON nc.SENDER_CONSUMER_ID=ces.CONSUMER_ID
AND cim.CONSUMER_INTEREST_EXPERT_ID=ces.CONSUMER_EXPERT_ID
JOIN survey_customer_similarity AS scs
ON cr.CONSUMER_ID=scs.CONSUMER_ID_2
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
OR cr.CONSUMER_ID=scs.CONSUMER_ID_1
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
CROSS JOIN
(
SELECT AVG(cal.TIPS_AMOUNT) AS AVG_TIPS
FROM CONSUMER_ACTION_LOG AS cal
JOIN (SELECT 234 AS CONSUMER_ID,
ACTION_LOG_ID,
COMMUNICATIONS_ID
FROM consumer_action_log
WHERE COMM_TYPE_ID=4) AS cr
ON cal.SENDER_CONSUMER_ID=cr.consumer_id
) ATV) AS ASM
GROUP BY ANSWER_ID
UNION
SELECT 1 AS RELEVANCE_SCORE_TYPE,
qcr.CONSUMER_ID AS Viewer_ID,
qcr.COMMUNICATIONS_ID,
case when reply.replies IS NOT NULL AND qcr.CONSUMER_ID <> qcr.SENDER_CONSUMER_ID then
24/((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(qcr.LAST_MOD_TIME)+3600)/3600)*(ces.EXPERT_SCORE+2.5*scs.SIMILARITY)*(EXP(-reply.replies))
when reply.replies IS NULL AND qcr.CONSUMER_ID <> qcr.SENDER_CONSUMER_ID then
24/((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(qcr.LAST_MOD_TIME)+3600)/3600)*(ces.EXPERT_SCORE+2.5*scs.SIMILARITY)*(EXP(0))
when reply.replies IS NULL AND qcr.CONSUMER_ID = qcr.SENDER_CONSUMER_ID then
24/((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(qcr.LAST_MOD_TIME)+3600)/3600)*(7.5)*(1-EXP(0))
when reply.replies IS NOT NULL AND qcr.CONSUMER_ID = qcr.SENDER_CONSUMER_ID then
24/((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(qcr.LAST_MOD_TIME)+3600)/3600)*(7.5)*(1-EXP(-reply.replies))
else null
end as QUESTION_SCORE
FROM (SELECT 238 AS CONSUMER_ID,
SENDER_CONSUMER_ID,
COMMUNICATIONS_ID,
LAST_MOD_TIME
FROM network_communications
WHERE NETWORK_COMM_TYPE_ID=1) AS qcr
JOIN communication_interest_mapping AS cim
ON qcr.COMMUNICATIONS_ID=cim.COMMUNICATION_ID
JOIN consumer_expert_score AS ces
ON ces.CONSUMER_ID=qcr.CONSUMER_ID
AND cim.CONSUMER_INTEREST_EXPERT_ID=ces.CONSUMER_EXPERT_ID
JOIN survey_customer_similarity AS scs
ON qcr.CONSUMER_ID=scs.CONSUMER_ID_2
AND qcr.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
OR qcr.CONSUMER_ID=scs.CONSUMER_ID_1
AND qcr.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
LEFT JOIN (SELECT COUNT(*) AS replies,
PARENT_COMMUNICATIONS_ID
FROM network_communications AS nc1
WHERE NETWORK_COMM_TYPE_ID=2
GROUP BY PARENT_COMMUNICATIONS_ID) AS reply
ON qcr.COMMUNICATIONS_ID=reply.PARENT_COMMUNICATIONS_ID
ORDER BY RELEVANCE_SCORE DESC;
FROM (SELECT 234 AS CONSUMER_ID,
ACTION_LOG_ID,
COMMUNICATIONS_ID
FROM consumer_action_log
WHERE COMM_TYPE_ID=4) AS cr
JOIN network_communications AS nc
ON cr.COMMUNICATIONS_ID=nc.COMMUNICATIONS_ID
JOIN consumer_action_log AS cal
ON cr.ACTION_LOG_ID=cal.ACTION_LOG_ID
JOIN communication_interest_mapping AS cim
ON nc.PARENT_COMMUNICATIONS_ID=cim.COMMUNICATION_ID
JOIN consumer_interest_rating_mapping AS cirm
ON cr.CONSUMER_ID=cirm.CONSUMER_ID
AND cim.CONSUMER_INTEREST_EXPERT_ID=cirm.CONSUMER_INTEREST_ID
JOIN consumer_expert_score AS ces
ON nc.SENDER_CONSUMER_ID=ces.CONSUMER_ID
AND cim.CONSUMER_INTEREST_EXPERT_ID=ces.CONSUMER_EXPERT_ID
JOIN survey_customer_similarity AS scs
ON cr.CONSUMER_ID=scs.CONSUMER_ID_2
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_1
OR cr.CONSUMER_ID=scs.CONSUMER_ID_1
AND cal.SENDER_CONSUMER_ID=scs.CONSUMER_ID_2
CROSS JOIN
(
SELECT AVG(cal.TIPS_AMOUNT) AS AVG_TIPS
FROM CONSUMER_ACTION_LOG AS cal
JOIN (SELECT 234 AS CONSUMER_ID,
ACTION_LOG_ID,
COMMUNICATIONS_ID
FROM consumer_action_log
WHERE COMM_TYPE_ID=4) AS cr
ON cal.SENDER_CONSUMER_ID=cr.consumer_id
) ATV) AS ASM
GROUP BY ANSWER_ID
ORDER BY ANSWER_SCORE_SUMMED DESC;
很长,所以不要觉得有必要阅读整篇文章。要点只是联盟两边的查询都使用了很多相同的表格。
答案 0 :(得分:2)
我的第一个想法是,不值得尝试超越MySQL优化器。特别是因为你正在进行18次连接和2次交叉连接。
UNION双方的查询使用大量相同的表并不罕见。这是我希望优化器能够处理的那种情况。
为了获得更好的性能,您需要查看执行配置文件,并可能重写查询以消除交叉连接。要查看执行配置文件,请运行这两个中的一个。
EXPLAIN <your query>
EXPLAIN EXTENDED <your query>
答案 1 :(得分:0)
看起来顶部和底部之间存在一些细微差别。因此,如果没有UNION
,请不要轻易重写。但是,如果您确定来自顶部和底部查询的数据不会重叠使用UNION ALL
,那么UNION
会尝试使结果不同,使引擎执行额外的工作,如果有有很多记录。
根据@ Catcall的建议,使用EXPLAIN
将验证UNION ALL
方法。