消除MySQL中的子查询

时间:2016-05-23 03:28:33

标签: mysql

我在MySQL中有一个表格,如下所示。

CREATE TABLE `myTable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `employeeNumber` int(11) DEFAULT NULL,  
  `approveDate` date DEFAULT NULL,
  `documentNumber` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `INDEX_1` (`documentNumber`)
) ENGINE=InnoDB;

如果documentNumber已获得employeeNumber批准或某些employeeNumber批准或未获得任何employeeNumber批准,我想进行查询。

我做了如下查询。

SELECT T1.documentNumber, 
 (CASE WHEN T2.currentNum = '0' THEN '1' WHEN T2.currentNum < T2.totalNum THEN '2' ELSE '3' END) AS approveStatusNumber
FROM myTable AS T1 LEFT JOIN
   (SELECT documentNumber, COUNT(*) AS totalNum, SUM(CASE WHEN approveDate IS NOT NULL THEN '1' ELSE '0' END) AS currentNum 
    FROM myTable GROUP by documentNumber) AS T2 ON T1.documentNumber = T2.documentNumber 
GROUP BY T1.documentNumber;

这个SQL有效,但速度很慢。 我在这个SQL上尝试explain,结果如下。

+----+-------------+------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra                                        |
+----+-------------+------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
|  1 | PRIMARY     | T1         | range | INDEX_1       | INDEX_1 | 153     | NULL |   27 | Using where; Using temporary; Using filesort |
|  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL | 5517 |                                              |
|  2 | DERIVED     | myTable    | index | NULL          | INDEX_1 | 153     | NULL | 5948 | Using where                                  |
+----+-------------+------------+-------+---------------+---------+---------+------+------+----------------------------------------------+

我认为我必须消除子查询以改进我的查询。 如果没有子查询,我怎么能做同样的事情?或者我有其他方法来改善我的查询?

1 个答案:

答案 0 :(得分:0)

返回currentNum的表达式可以更简洁地表达(在MySQL中)

  SUM(approveDate IS NOT NULL)

并且不需要内联视图。这将返回相同的结果:

SELECT t.documentNumber
     , CASE 
         WHEN SUM(t.approveDate IS NOT NULL) = 0 
           THEN '1'
         WHEN SUM(t.approveDate IS NOT NULL) < COUNT(*)
           THEN '2'
         ELSE '3'
       END AS approveStatusNumber
  FROM myTable t
 GROUP BY t.documentNumber
 ORDER BY t.documentNumber