SELECT a.emp_id,s.name, s.department,s.register, z.Compoff_Count as Extra, ifnull(COUNT(DISTINCT TO_DAYS(a.punchdate)),0) as Monthly_Count
FROM machinedata a left join
(SELECT a.emp_id, ifnull(COUNT(DISTINCT TO_DAYS(a.punchdate)),0) as Compoff_Count
FROM machinedata a
RIght JOIN time_dimension c on c.db_date = a.punchdate
where ( year(c.db_date) = 2016 and month(c.db_date) = 8 and (c.holiday_flag = 't' or c.weekend_flag ='t' ))
GROUP BY a.emp_id) Z
on z.emp_id = a.emp_id
RIght JOIN time_dimension c on c.db_date = a.punchdate
left join emp s on s.emp_id = a.emp_id
where (year(c.db_date) = 2016 and month(c.db_date) = 8 and c.holiday_flag = 'f' and c.weekend_flag ='f' )
GROUP BY emp_id
以上查询工作正常..但如果我添加s.department ='是'在查询占用超过40秒的最后一个。
我该怎么做才能提高查询性能?
答案 0 :(得分:0)
您的初始查询可以简化我相信使用“条件聚合”将case表达式放在count()函数中。这避免了重复的数据传播和对派生表的不必要的连接。
您还应该避免在数据上使用函数来适应where子句条件,即,而不是YEAR()和MONTH()只使用日期边界。这允许在查询执行中使用日期列上的索引。
我不确定你是否真的需要使用TO_DAYS(),但我怀疑它也不需要。
SELECT
a.emp_id
, s.name
, s.department
, s.register
, COUNT(DISTINCT CASE WHEN (c.holiday_flag = 't' OR
c.weekend_flag = 't') THEN c.db_date END) AS Compoff_Count
, COUNT(DISTINCT CASE WHEN NOT (c.holiday_flag = 't' OR
c.weekend_flag = 't') THEN a.punchdate END) AS Monthly_Count
FROM time_dimension c
LEFT JOIN machinedata a ON c.db_date = a.punchdate
LEFT JOIN emp s ON a.emp_id = s.emp_id
WHERE c.db_date >= '2016-08-01'
AND c.db_date < '2016-09-01'
GROUP BY
a.emp_id
, s.name
, s.department
, s.register
如果重新编写产生正确的结果,那么您可以尝试将和s.department ='yes'添加到where子句中以评估影响。如果它仍然大大慢,那么得到解释计划并将其添加到问题中。缓慢的最可能原因是缺乏指数但没有解释计划则无法确定。
请注意,这个建议就是这样;并准备没有样本数据和预期结果。