2016-11-14 37 views
-1
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

https://dev.mysql.com/doc/refman/5.5/en/where-optimizations.html –

+0

涉及的表的大小是多少?什么是结构?你可以在查询中使用EXPLAIN并发布结果吗? – Loufylouf

+0

可能您的请求没有部门=“是”只是缓存,请为两个查询提供EXPLAIN输出 – 2oppin

回答

0

您的初始查询可以简化我相信通过使用“条件聚合”,其中的情况表达式放置在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 =“是”到where子句来评估影响。如果它仍然很慢,那么得到一个解释计划并将其添加到问题中。缓慢的最可能原因是缺乏索引,但没有解释计划是不可能确定的。

请注意,这个建议就是这样;并且没有样本数据和预期结果。

+0

感谢它的工作! – sandy12321

+0

太好了。顺便说一下,这是一个不成文的惯例 - 为了避免重大的头痛 - 一个不使用正确的连接。正确的连接是合法的语法,但实际上它很难遵循,尤其是如果你在单个查询中多次执行它。只是一个小费。没有比这更多。 –