diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index b889d0310797cba3ad85717d8021ed99fe2448c8..6370f7699b3e375a1d8508dbbe3a24d212d50df8 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -1954,6 +1954,15 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	index	idx_t1_0,idx_t1_1,idx_t1_2	idx_t1_1	163	NULL	128	Using where; Using index
+explain select distinct(a1) from t1 where ord(a2) = 98;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	index	NULL	idx_t1_1	163	NULL	128	Using where; Using index
+select distinct(a1) from t1 where ord(a2) = 98;
+a1
+a
+b
+c
+d
 explain select a1 from t1 where a2 = 'b' group by a1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	NULL	idx_t1_1	130	NULL	5	Using where; Using index for group-by
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index 0f0a632ff670152e864dde2554a23f7e6d129d97..bff07366ec2e7e00d70250d0a7a0252b0e92842b 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -641,6 +641,14 @@ explain select a1,a2,count(a2) from t1 group by a1,a2,b;
 explain select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
 explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
 
+
+#
+# Bug #16710: select distinct doesn't return all it should
+#
+
+explain select distinct(a1) from t1 where ord(a2) = 98;
+select distinct(a1) from t1 where ord(a2) = 98;
+
 #
 # BUG#11044: DISTINCT or GROUP BY queries with equality predicates instead of MIN/MAX.
 #
diff --git a/sql/item.cc b/sql/item.cc
index 885617669a97c30bee75605e09cf0470b550dfc3..466216ffb78a84823974bacbd622020928ea6ea1 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -496,7 +496,7 @@ bool Item_ident::remove_dependence_processor(byte * arg)
     arguments in a condition the method must return false.
 
   RETURN
-    false to force the evaluation of collect_item_field_processor
+    FALSE to force the evaluation of collect_item_field_processor
           for the subsequent items.
 */
 
@@ -517,6 +517,38 @@ bool Item_field::collect_item_field_processor(byte *arg)
 }
 
 
+/*
+  Check if an Item_field references some field from a list of fields.
+
+  SYNOPSIS
+    Item_field::find_item_in_field_list_processor
+    arg   Field being compared, arg must be of type Field
+
+  DESCRIPTION
+    Check whether the Item_field represented by 'this' references any
+    of the fields in the keyparts passed via 'arg'. Used with the
+    method Item::walk() to test whether any keypart in a sequence of
+    keyparts is referenced in an expression.
+
+  RETURN
+    TRUE  if 'this' references the field 'arg'
+    FALE  otherwise
+*/
+bool Item_field::find_item_in_field_list_processor(byte *arg)
+{
+  KEY_PART_INFO *first_non_group_part= *((KEY_PART_INFO **) arg);
+  KEY_PART_INFO *last_part= *(((KEY_PART_INFO **) arg) + 1);
+  KEY_PART_INFO *cur_part;
+
+  for (cur_part= first_non_group_part; cur_part != last_part; cur_part++)
+  {
+    if (field->eq(cur_part->field))
+      return TRUE;
+  }
+  return FALSE;
+}
+
+
 bool Item::check_cols(uint c)
 {
   if (c != 1)
diff --git a/sql/item.h b/sql/item.h
index b9ce418858c7ca1d4cb08fb85a002de5f18fe72f..6c7a0976df1bc25a8cae27583839368509611752 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -741,6 +741,7 @@ public:
   virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
   virtual bool cleanup_processor(byte *arg);
   virtual bool collect_item_field_processor(byte * arg) { return 0; }
+  virtual bool find_item_in_field_list_processor(byte *arg) { return 0; }
   virtual bool change_context_processor(byte *context) { return 0; }
   virtual bool reset_query_id_processor(byte *query_id) { return 0; }
 
@@ -1193,6 +1194,7 @@ public:
   bool is_null() { return field->is_null(); }
   Item *get_tmp_table_item(THD *thd);
   bool collect_item_field_processor(byte * arg);
+  bool find_item_in_field_list_processor(byte *arg);
   bool reset_query_id_processor(byte *arg)
   {
     field->query_id= *((query_id_t *) arg);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 4ffce67638d724e2298aa4805198cd3a4aeaedd0..7f93327f68a71008565b6499d466ca4e38c3b1fc 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -8189,6 +8189,7 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
                    bool have_min, bool have_max,
                    double *read_cost, ha_rows *records);
 
+
 /*
   Test if this access method is applicable to a GROUP query with MIN/MAX
   functions, and if so, construct a new TRP object.
@@ -8595,11 +8596,36 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
       }
       else if (min_max_arg_part &&
                (min_max_arg_part - first_non_group_part > 0))
+      {
         /*
           There is a gap but no range tree, thus no predicates at all for the
           non-group keyparts.
         */
         goto next_index;
+      }
+      else if (first_non_group_part && join->conds)
+      {
+        /*
+          If there is no MIN/MAX function in the query, but some index
+          key part is referenced in the WHERE clause, then this index
+          cannot be used because the WHERE condition over the keypart's
+          field cannot be 'pushed' to the index (because there is no
+          range 'tree'), and the WHERE clause must be evaluated before
+          GROUP BY/DISTINCT.
+        */
+        /*
+          Store the first and last keyparts that need to be analyzed
+          into one array that can be passed as parameter.
+        */
+        KEY_PART_INFO *key_part_range[2];
+        key_part_range[0]= first_non_group_part;
+        key_part_range[1]= last_part;
+
+        /* Check if cur_part is referenced in the WHERE clause. */
+        if (join->conds->walk(&Item::find_item_in_field_list_processor,
+                              (byte*) key_part_range))
+          goto next_index;
+      }
     }
 
     /*