说明: Complaint_status包含多行用于特定投诉,试图获得用户明智的关闭投诉(状态= 2且值IN(1,2))
痛点:
YEAR(cs.created_at)=year(curdate())
AND MONTH(cs.created_at)=month(curdate())
在本地服用近5分钟,在服务器上服用1.5分钟
SELECT u3.name,COUNT(c3.id) as closed_tickets
FROM complaint c3,complaint_status cs,assignment a3,user u3
WHERE
c3.id=cs.complaint_id
AND a3.complaint_id=c3.id
AND u3.id=a3.assigned_to
AND u3.user_type=14
AND a3.expiry IS NULL
AND cs.id IN(SELECT MAX(id) FROM complaint_status WHERE complaint_id=c3.id AND status=2 AND value IN(1,2))
AND YEAR(cs.created_at)=year(curdate())
AND MONTH(cs.created_at)=month(curdate())
GROUP BY u3.id
ORDER BY COUNT(c3.id) DESC
答案 0 :(得分:1)
在WHERE
子句中应用此谓词的问题:
YEAR(cs.created_at)=year(curdate())
AND MONTH(cs.created_at)=month(curdate())
MySql是否需要为所有记录(或至少剩余的记录)评估这些函数。这里的浪费是这些有效的常数,取决于当前的日期。假设created_at
上有一个索引,您可以通过将日期与本月的第一天进行比较,而不是将下个月的第一天进行比较,来提高hitting the index的可能性(并假设created_at
是DATE):
...
cs.created_at >= DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY),
AND cs.created_at < DATE_ADD(LAST_DAY(CURRENT_DATE), INTERVAL + 1 DAY)
请注意,结束日期不包括上限(因为这可能包括下个月第一秒的数据)
答案 1 :(得分:1)
首先,您应该修复join
状态。
其次,而不是:
YEAR(cs.created_at) = year(curdate()) AND MONTH(cs.created_at) = month(curdate())
使用:
cs.created_at >= curdate() and cs_created_at < date_sub(date_sub, curdate(), interval day(curdate()) - 1, interval 1 month)
这将允许该字段使用具有created_at
。
这似乎是您的具体问题。
如果你真的想要优化查询,我建议用问另一个问题:
答案 2 :(得分:1)
尝试:
SELECT u3.name,
COUNT(c3.id) AS closed_tickets
FROM complaint c3
JOIN complaint_status cs
ON c3.id=cs.complaint_id
JOIN ASSIGNMENT a3
ON a3.complaint_id=c3.id
JOIN USER u3
ON u3.id=a3.assigned_to
JOIN (SELECT complaint_id,
MAX(id) id
FROM complaint_status
WHERE status=2
AND value IN(1,2)
GROUP BY complaint_id) cs9
ON cs9.complaint_id=c3.id
AND cs.id = cs9.id
WHERE u3.user_type=14
AND a3.expiry IS NULL
AND cs.created_at >= DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY)
AND cs.created_at < DATE_ADD(LAST_DAY(CURRENT_DATE), INTERVAL + 1 DAY)
GROUP BY u3.id
ORDER BY COUNT(c3.id) DESC