diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result
index c141b2557169b3f851f3bc90641abaac2c1e5ad3..c9ef41e058243ad310f8420edb36a1d6c8239f14 100644
--- a/mysql-test/r/compare.result
+++ b/mysql-test/r/compare.result
@@ -53,3 +53,41 @@ a	b
 Warnings:
 Warning	1292	Truncated incorrect DOUBLE value: ''
 drop table if exists t1;
+CREATE TABLE  t1 (b int(2) zerofill, c int(2) zerofill);
+INSERT INTO t1 (b,c) VALUES (1,2), (1,1), (2,2);
+SELECT CONCAT(b,c), CONCAT(b,c) = '0101' FROM t1;
+CONCAT(b,c)	CONCAT(b,c) = '0101'
+0102	0
+0101	1
+0202	0
+EXPLAIN EXTENDED SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
+Warnings:
+Note	1003	select `test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`b` = 1) and (concat(_binary'01',`test`.`t1`.`c`) = _latin1'0101'))
+SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101';
+b	c
+01	01
+CREATE TABLE t2 (a int);
+INSERT INTO t2 VALUES (1),(2);
+SELECT a, 
+(SELECT COUNT(*) FROM t1 
+WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x 
+FROM t2 ORDER BY a;
+a	x
+1	1
+2	0
+EXPLAIN EXTENDED 
+SELECT a, 
+(SELECT COUNT(*) FROM t1 
+WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x 
+FROM t2 ORDER BY a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	2	Using filesort
+2	DEPENDENT SUBQUERY	t1	ALL	NULL	NULL	NULL	NULL	3	Using where
+Warnings:
+Note	1276	Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
+Note	1276	Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
+Note	1003	select `test`.`t2`.`a` AS `a`,(select count(0) AS `COUNT(*)` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t2`.`a`) and (concat(`test`.`t1`.`b`,`test`.`t1`.`c`) = concat(_latin1'0',`test`.`t2`.`a`,_latin1'01')))) AS `x` from `test`.`t2` order by `test`.`t2`.`a`
+DROP TABLE t1,t2;
+End of 5.0 tests
diff --git a/mysql-test/t/compare.test b/mysql-test/t/compare.test
index 337035a8095e84574f11c638ad32545489c1023d..8863ed825c2cdb0eb37c206223ba1bbf19b3abeb 100644
--- a/mysql-test/t/compare.test
+++ b/mysql-test/t/compare.test
@@ -46,3 +46,34 @@ insert into t1 values (0x01,0x01);
 select * from t1 where a=b;
 select * from t1 where a=b and b=0x01;
 drop table if exists t1;
+
+#
+# Bug #31887: DML Select statement not returning same results when executed
+# in version 5
+#
+
+CREATE TABLE  t1 (b int(2) zerofill, c int(2) zerofill);
+INSERT INTO t1 (b,c) VALUES (1,2), (1,1), (2,2);
+
+SELECT CONCAT(b,c), CONCAT(b,c) = '0101' FROM t1;
+
+EXPLAIN EXTENDED SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101';
+SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101';
+
+CREATE TABLE t2 (a int);
+INSERT INTO t2 VALUES (1),(2);
+
+SELECT a, 
+  (SELECT COUNT(*) FROM t1 
+   WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x 
+FROM t2 ORDER BY a;
+
+EXPLAIN EXTENDED 
+SELECT a, 
+  (SELECT COUNT(*) FROM t1 
+   WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x 
+FROM t2 ORDER BY a;
+
+DROP TABLE t1,t2;
+
+--echo End of 5.0 tests
diff --git a/sql/item.cc b/sql/item.cc
index 3555df40060cfbab1521ce2155a4ef210b3d22c6..e3e17a3ceea843f4beb608ccb6871fc7235aad3f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4072,6 +4072,30 @@ bool Item_field::subst_argument_checker(byte **arg)
 }
 
 
+/**
+  Convert a numeric value to a zero-filled string
+
+  @param[in,out]  item   the item to operate on
+  @param          field  The field that this value is equated to
+
+  This function converts a numeric value to a string. In this conversion
+  the zero-fill flag of the field is taken into account.
+  This is required so the resulting string value can be used instead of
+  the field reference when propagating equalities.
+*/
+
+static void convert_zerofill_number_to_string(Item **item, Field_num *field)
+{
+  char buff[MAX_FIELD_WIDTH],*pos;
+  String tmp(buff,sizeof(buff), field->charset()), *res;
+
+  res= (*item)->val_str(&tmp);
+  field->prepend_zeros(res);
+  pos= (char *) sql_strmake (res->ptr(), res->length());
+  *item= new Item_string(pos, res->length(), field->charset());
+}
+
+
 /*
   Set a pointer to the multiple equality the field reference belongs to
   (if any)
@@ -4120,6 +4144,13 @@ Item *Item_field::equal_fields_propagator(byte *arg)
   if (!item ||
       (cmp_context != (Item_result)-1 && item->cmp_context != cmp_context))
     item= this;
+  else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type()))
+  {
+    if (item && cmp_context != INT_RESULT)
+      convert_zerofill_number_to_string(&item, (Field_num *)field);
+    else
+      item= this;
+  }
   return item;
 }
 
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 47396748da6eafbc54e0f93d0d5d39b8f48172e3..821495ddecbb7e2f1e35aec575177689b69c6299 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -73,6 +73,7 @@ extern const char *primary_key_name;
 #include "mysql_com.h"
 #include <violite.h>
 #include "unireg.h"
+#define IS_NUM(t)	((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL)
 
 void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size);
 gptr sql_alloc(unsigned size);