Bug #49605 MIN() not functioning for certain queries without the use of indexes
Submitted: 10 Dec 2009 22:13 Modified: 7 Feb 2018 21:55
Reporter: Patrick Crews Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:5.0+ OS:Any
Assigned to: CPU Architecture:Any
Tags: INDEX, min()

[10 Dec 2009 22:13] Patrick Crews
Description:
The MIN() function is not working properly for certain queries without the use of indexes:

For this query (from the test case):
SELECT  MIN( table1 .`col_int_key`  )        
FROM C table1  LEFT  JOIN (
SELECT SUBQUERY1_t1 .*
FROM C SUBQUERY1_t1  JOIN ( C SUBQUERY1_t2  STRAIGHT_JOIN BB SUBQUERY1_t3  ON SUBQUERY1_t3 .`pk`  = SUBQUERY1_t2 .`pk`  )  ON SUBQUERY1_t3 .`col_int_nokey`  = SUBQUERY1_t2 .`pk`  ) table2  ON table2 .`pk`   ORDER BY table1.col_int_key ;

We will either get NULL or 0 depending on whether or not we are using indexes other than the pk, respectively.

Looking at just the rows returned (no MIN), we get identical result sets:
SELECT SUBQUERY1_t1 .*
FROM C SUBQUERY1_t1  JOIN ( C SUBQUERY1_t2  STRAIGHT_JOIN BB SUBQUERY1_t3  ON SUBQUERY1_t3 .`pk`  = SUBQUERY1_t2 .`pk`  )  ON SUBQUERY1_t3 .`col_int_nokey`  = SUBQUERY1_t2 .`pk`  ) table2  ON table2 .`pk`   ORDER BY table1.col_int_key ;
col_int_key
NULL
0
0
1
2
2
3
3
3
5
5
6
8
8
9
9
9
9
53
166

EXPLAIN (with index):
EXPLAIN SELECT  MIN( table1 .`col_int_key`  )
FROM C table1  LEFT  JOIN (
SELECT SUBQUERY1_t1 .*
FROM C SUBQUERY1_t1  JOIN ( C SUBQUERY1_t2  STRAIGHT_JOIN BB SUBQUERY1_t3  ON SUBQUERY1_t3 .`pk`  = SUBQUERY1_t2 .`pk`  )  ON SUBQUERY1_t3 .`col_int_nokey`  = SUBQUERY1_t2 .`pk`  ) table2  ON table2 .`pk`   ;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
2	DERIVED	SUBQUERY1_t1	ALL	NULL	NULL	NULL	NULL	20	
2	DERIVED	SUBQUERY1_t2	index	PRIMARY	PRIMARY	4	NULL	20	Using index
2	DERIVED	SUBQUERY1_t3	ALL	PRIMARY	NULL	NULL	NULL	1	Using where

EXPLAIN (without index other than pk):
EEXPLAIN SELECT  MIN( table1 .`col_int_key`  )
FROM C table1  LEFT  JOIN (
SELECT SUBQUERY1_t1 .*
FROM C SUBQUERY1_t1  JOIN ( C SUBQUERY1_t2  STRAIGHT_JOIN BB SUBQUERY1_t3  ON SUBQUERY1_t3 .`pk`  = SUBQUERY1_t2 .`pk`  )  ON SUBQUERY1_t3 .`col_int_nokey`  = SUBQUERY1_t2 .`pk`  ) table2  ON table2 .`pk`   ;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	0	const row not found
1	PRIMARY	table1	ALL	NULL	NULL	NULL	NULL	20	
2	DERIVED	SUBQUERY1_t1	ALL	NULL	NULL	NULL	NULL	20	
2	DERIVED	SUBQUERY1_t2	index	PRIMARY	PRIMARY	4	NULL	20	Using index
2	DERIVED	SUBQUERY1_t3	ALL	PRIMARY	NULL	NULL	NULL	1	Using where

How to repeat:
MTR test case, set up for use with 6.0.  Please comment / uncomment SET statements as needed for use with earlier versions of the server:
#/* Server0: MySQL 6.0.14-alpha-gcov-debug-log */

#/*!50400 SET SESSION optimizer_switch = 'firstmatch=off,index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,loosescan=off,materialization=off,semijoin=off' */;
#/*!50400 SET SESSION optimizer_use_mrr = 'force' */;
#/*!50400 SET SESSION engine_condition_pushdown = 'ON' */;
#/*!50400 SET SESSION join_cache_level = 1 */;
#/*!50400 SET SESSION debug = 'd,optimizer_no_icp,optimizer_innodb_ds_mrr' */;

#/* Begin test case for query 0 */

--disable_warnings
DROP TABLE /*! IF EXISTS */ BB;
DROP TABLE /*! IF EXISTS */ C;
--enable_warnings

CREATE TABLE `BB` (
  `pk` int(11) NOT NULL AUTO_INCREMENT,
  `col_int_nokey` int(11) DEFAULT NULL,
  `col_int_key` int(11) DEFAULT NULL,
  PRIMARY KEY (`pk`),
  KEY `col_int_key` (`col_int_key`),
  KEY `col_varchar_key` (`col_int_key`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;
INSERT INTO `BB` VALUES (10,8,8);
CREATE TABLE `C` (
  `pk` int(11) NOT NULL AUTO_INCREMENT,
  `col_int_nokey` int(11) DEFAULT NULL,
  `col_int_key` int(11) DEFAULT NULL,
  PRIMARY KEY (`pk`),
  KEY `col_int_key` (`col_int_key`),
  KEY `col_varchar_key` (`col_int_key`)
) ENGINE=MyISAM AUTO_INCREMENT=21 DEFAULT CHARSET=latin1;
INSERT INTO `C` VALUES (1,NULL,2);
INSERT INTO `C` VALUES (2,7,9);
INSERT INTO `C` VALUES (3,9,3);
INSERT INTO `C` VALUES (4,7,9);
INSERT INTO `C` VALUES (5,4,NULL);
INSERT INTO `C` VALUES (6,2,9);
INSERT INTO `C` VALUES (7,6,3);
INSERT INTO `C` VALUES (8,8,8);
INSERT INTO `C` VALUES (9,NULL,8);
INSERT INTO `C` VALUES (10,5,53);
INSERT INTO `C` VALUES (11,NULL,0);
INSERT INTO `C` VALUES (12,6,5);
INSERT INTO `C` VALUES (13,188,166);
INSERT INTO `C` VALUES (14,2,3);
INSERT INTO `C` VALUES (15,1,0);
INSERT INTO `C` VALUES (16,1,1);
INSERT INTO `C` VALUES (17,0,9);
INSERT INTO `C` VALUES (18,9,5);
INSERT INTO `C` VALUES (19,NULL,6);
INSERT INTO `C` VALUES (20,4,2);

 
SELECT  MIN( table1 .`col_int_key`  )  
FROM C table1  LEFT  JOIN (  
SELECT SUBQUERY1_t1 .* 
FROM C SUBQUERY1_t1  JOIN ( C SUBQUERY1_t2  STRAIGHT_JOIN BB SUBQUERY1_t3  ON SUBQUERY1_t3 .`pk`  = SUBQUERY1_t2 .`pk`  )  ON SUBQUERY1_t3 .`col_int_nokey`  = SUBQUERY1_t2 .`pk`  ) table2  ON table2 .`pk`   ;

#/* End of test case for query 0 */

#/* Begin test case for query 1 */

ALTER TABLE C DROP KEY col_int_key;
ALTER TABLE C DROP KEY col_varchar_key;
ALTER TABLE BB DROP KEY col_int_key;
ALTER TABLE BB DROP KEY col_varchar_key;

SELECT  MIN( table1 .`col_int_key`  )  
FROM C table1  LEFT  JOIN (  
SELECT SUBQUERY1_t1 .* 
FROM C SUBQUERY1_t1  JOIN ( C SUBQUERY1_t2  STRAIGHT_JOIN BB SUBQUERY1_t3  ON SUBQUERY1_t3 .`pk`  = SUBQUERY1_t2 .`pk`  )  ON SUBQUERY1_t3 .`col_int_nokey`  = SUBQUERY1_t2 .`pk`  ) table2  ON table2 .`pk`   /* TRANSFORM_OUTCOME_UNORDERED_MATCH */; 

DROP TABLE BB;
DROP TABLE C;
#/* End of test case for query 1 */
[6 Feb 2018 19:35] Sveta Smirnova
With 5.7 both queries return 0
[7 Feb 2018 21:55] Roy Lyseng
Posted by developer:
 
Fixed in 5.6 and up.