Repository: apache/shardingsphere
Issue: "select code from t group by code" got duplicate records

## Bug Report

### Which version of ShardingSphere did you use?
3.0.0

### Which project did you use? Sharding-JDBC or Sharding-Proxy?
Sharding-Proxy

### Expected behavior
I have a logic table 't' with 2 shards, actual table are 't_0' and 't_1'.
When I excute "select code from t group by code" on Sharding-Proxy-3.0.0,
it should returns code without duplicate.

### Actual behavior
but in fact, it returns duplicate records.

### Reason analyze (If you can)
My backend db is mysql5.7.  
COLLATE is 'utf8mb4_unicode_ci'.

The group-by merger may add 'order by code' clause for using stream merge,
and the result set is sorted by case insensitive.
But the merger compares value with case sensitive(because use java compareTo method).

### Steps to reproduce the behavior, such as: SQL to execute, sharding rule configuration, when exception occur etc.



#### sharding rule:

```
  tables:
    t:
      actualDataNodes: ds_${0}.t_${0..1}
      tableStrategy:
        inline:
          shardingColumn: id
          algorithmExpression: t_${id % 2}
```

#### prepare sql script:

```
CREATE TABLE `t_0` (
	`id` INT NOT NULL,
	`code` VARCHAR(40) NOT NULL,
	PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_unicode_ci'
;
CREATE TABLE `t_1` (
	`id` INT NOT NULL,
	`code` VARCHAR(40) NOT NULL,
	PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_unicode_ci'
;
insert into t values (11, '11035801128253');
insert into t values (13, '110358011282f5');
insert into t values (15, '110358011282G1');
insert into t values (17, '110358011282H5');
insert into t values (19, '110358011282T4');
insert into t values (21, '110358011282U5');
insert into t values (23, '110358011282z1');
insert into t values (22, '110358011282D4');
insert into t values (24, '110358011282E9');
insert into t values (26, '110358011282h8');
insert into t values (28, '110358011282I0');
insert into t values (30, '110358011282l1');
insert into t values (32, '110358011282O7');
insert into t values (34, '110358011282P0');
insert into t values (36, '110358011282T4');
insert into t values (38, '110358011282w6');


mysql> select 't_0' as tab, code from t_0;
+------+----------------+
| tab  | code           |
+------+----------------+
| t_0  | 110358011282D4 |
| t_0  | 110358011282E9 |
| t_0  | 110358011282h8 |
| t_0  | 110358011282I0 |
| t_0  | 110358011282l1 |
| t_0  | 110358011282O7 |
| t_0  | 110358011282P0 |
| t_0  | 110358011282T4 |
| t_0  | 110358011282w6 |
+------+----------------+
9 rows in set (0.00 sec)

mysql> select 't_1' as tab, code from t_1;
+------+----------------+
| tab  | code           |
+------+----------------+
| t_1  | 11035801128253 |
| t_1  | 110358011282f5 |
| t_1  | 110358011282G1 |
| t_1  | 110358011282H5 |
| t_1  | 110358011282T4 |
| t_1  | 110358011282U5 |
| t_1  | 110358011282z1 |
+------+----------------+
7 rows in set (0.00 sec)
```

#### execute result  ( duplicate code is 110358011282T4 .)

```
mysql> select code from t group by code;
+----------------+
| code           |
+----------------+
| 11035801128253 |
| 110358011282D4 |
| 110358011282E9 |
| 110358011282f5 |
| 110358011282G1 |
| 110358011282H5 |
| 110358011282T4 |
| 110358011282U5 |
| 110358011282h8 |
| 110358011282I0 |
| 110358011282l1 |
| 110358011282O7 |
| 110358011282P0 |
| 110358011282T4 |
| 110358011282w6 |
| 110358011282z1 |
+----------------+
16 rows in set (0.01 sec)
```

I tried following SQL then I got right result.

```
mysql> select max(code) from t group by upper(code);
+----------------+
| max(code)      |
+----------------+
| 11035801128253 |
| 110358011282D4 |
| 110358011282E9 |
| 110358011282f5 |
| 110358011282G1 |
| 110358011282H5 |
| 110358011282h8 |
| 110358011282I0 |
| 110358011282l1 |
| 110358011282O7 |
| 110358011282P0 |
| 110358011282T4 |
| 110358011282U5 |
| 110358011282w6 |
| 110358011282z1 |
+----------------+
15 rows in set (0.01 sec)

```


### Example codes for reproduce this issue (such as a github link).


Changed files:
sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/MemoryQueryResult.java
sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparator.java
sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/AggregationDistinctQueryResult.java
sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaDataTest.java
sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtil.java
sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResult.java
sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparatorTest.java
sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByMemoryMergedResult.java
sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/StreamQueryResult.java
sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValue.java
sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/DQLMergeEngineTest.java
sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResultTest.java
sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/fixture/TestQueryResult.java
sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByStreamMergedResultTest.java
sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResult.java
sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValueTest.java
sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaData.java
sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtilTest.java

diff --git a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/AggregationDistinctQueryResult.java b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/AggregationDistinctQueryResult.java
index 21aa167a257..c41132d2dc8 100644
--- a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/AggregationDistinctQueryResult.java
+++ b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/AggregationDistinctQueryResult.java
@@ -45,8 +45,9 @@ public final class AggregationDistinctQueryResult extends DistinctQueryResult {
     
     private final AggregationDistinctQueryMetaData metaData;
         
-    private AggregationDistinctQueryResult(final Multimap<String, Integer> columnLabelAndIndexMap, final Iterator<QueryRow> resultData, final AggregationDistinctQueryMetaData distinctQueryMetaData) {
-        super(columnLabelAndIndexMap, resultData);
+    private AggregationDistinctQueryResult(final Multimap<String, Integer> columnLabelAndIndexMap, final List<Boolean> columnCaseSensitive, final Iterator<QueryRow> resultData,
+        final AggregationDistinctQueryMetaData distinctQueryMetaData) {
+        super(columnLabelAndIndexMap, columnCaseSensitive, resultData);
         metaData = distinctQueryMetaData;
     }
     
@@ -75,7 +76,7 @@ public final class AggregationDistinctQueryResult extends DistinctQueryResult {
             public DistinctQueryResult apply(final QueryRow input) {
                 Set<QueryRow> resultData = new LinkedHashSet<>();
                 resultData.add(input);
-                return new AggregationDistinctQueryResult(getColumnLabelAndIndexMap(), resultData.iterator(), metaData);
+                return new AggregationDistinctQueryResult(getColumnLabelAndIndexMap(), getColumnCaseSensitive(), resultData.iterator(), metaData);
             }
         }));
     }
diff --git a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResult.java b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResult.java
index 340995edd4e..4ea938bbfad 100644
--- a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResult.java
+++ b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResult.java
@@ -46,6 +46,7 @@ import java.util.Set;
  * Distinct query result.
  *
  * @author panjuan
+ * @author yangyi
  */
 @RequiredArgsConstructor
 @Getter(AccessLevel.PROTECTED)
@@ -53,6 +54,8 @@ public class DistinctQueryResult implements QueryResult {
     
     private final Multimap<String, Integer> columnLabelAndIndexMap;
     
+    private final List<Boolean> columnCaseSensitive;
+    
     private final Iterator<QueryRow> resultData;
     
     private QueryRow currentRow;
@@ -60,6 +63,7 @@ public class DistinctQueryResult implements QueryResult {
     @SneakyThrows
     public DistinctQueryResult(final Collection<QueryResult> queryResults, final List<String> distinctColumnLabels) {
         this.columnLabelAndIndexMap = getColumnLabelAndIndexMap(queryResults.iterator().next());
+        this.columnCaseSensitive = getColumnCaseSensitive(queryResults.iterator().next());
         resultData = getResultData(queryResults, distinctColumnLabels);
     }
     
@@ -72,6 +76,15 @@ public class DistinctQueryResult implements QueryResult {
         return result;
     }
     
+    @SneakyThrows
+    private List<Boolean> getColumnCaseSensitive(final QueryResult queryResult) {
+        List<Boolean> result = Lists.newArrayList(false);
+        for (int columnIndex = 1; columnIndex <= queryResult.getColumnCount(); columnIndex++) {
+            result.add(queryResult.isCaseSensitive(columnIndex));
+        }
+        return result;
+    }
+    
     @SneakyThrows
     private Iterator<QueryRow> getResultData(final Collection<QueryResult> queryResults, final List<String> distinctColumnLabels) {
         Set<QueryRow> result = new LinkedHashSet<>();
@@ -111,7 +124,7 @@ public class DistinctQueryResult implements QueryResult {
             public DistinctQueryResult apply(final QueryRow row) {
                 Set<QueryRow> resultData = new LinkedHashSet<>();
                 resultData.add(row);
-                return new DistinctQueryResult(columnLabelAndIndexMap, resultData.iterator());
+                return new DistinctQueryResult(columnLabelAndIndexMap, columnCaseSensitive, resultData.iterator());
             }
         }));
     }
@@ -171,6 +184,11 @@ public class DistinctQueryResult implements QueryResult {
         return null == currentRow;
     }
     
+    @Override
+    public boolean isCaseSensitive(final int columnIndex) {
+        return columnCaseSensitive.get(columnIndex);
+    }
+    
     @Override
     public int getColumnCount() {
         return columnLabelAndIndexMap.size();
diff --git a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/MemoryQueryResult.java b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/MemoryQueryResult.java
index 78ad276831d..5ba4b6d9eee 100644
--- a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/MemoryQueryResult.java
+++ b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/MemoryQueryResult.java
@@ -41,6 +41,7 @@ import java.util.List;
  *
  * @author zhangliang
  * @author panjuan
+ * @author yangyi
  */
 public final class MemoryQueryResult implements QueryResult {
     
@@ -136,6 +137,11 @@ public final class MemoryQueryResult implements QueryResult {
         return null == currentRow;
     }
     
+    @Override
+    public boolean isCaseSensitive(final int columnIndex) {
+        return metaData.isCaseSensitive(columnIndex);
+    }
+    
     @Override
     public int getColumnCount() {
         return metaData.getColumnCount();
diff --git a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResult.java b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResult.java
index 2e1b277b39e..11248cad0fa 100644
--- a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResult.java
+++ b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResult.java
@@ -25,6 +25,7 @@ import java.util.Calendar;
  * Query result form database.
  *
  * @author zhangliang
+ * @author yangyi
  */
 public interface QueryResult {
     
@@ -122,4 +123,13 @@ public interface QueryResult {
      * @throws SQLException SQL Exception
      */
     boolean wasNull() throws SQLException;
+    
+    /**
+     * Whether the column value is case sensitive.
+     *
+     * @param columnIndex column index
+     * @return true if column is case sensitive, otherwise false
+     * @throws SQLException SQL Exception
+     */
+    boolean isCaseSensitive(int columnIndex) throws SQLException;
 }
diff --git a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaData.java b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaData.java
index 62e9a65241e..3f928bba4d6 100644
--- a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaData.java
+++ b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaData.java
@@ -34,6 +34,7 @@ import java.util.TreeMap;
  * Query result meta data.
  *
  * @author panjuan
+ * @author yangyi
  */
 public final class QueryResultMetaData {
     
@@ -120,6 +121,17 @@ public final class QueryResultMetaData {
         return columnLabelAndIndexes.get(columnLabel);
     }
     
+    /**
+     * Whether the column value is case sensitive.
+     *
+     * @param columnIndex column index
+     * @return true if column is case sensitive, otherwise false
+     */
+    @SneakyThrows
+    public boolean isCaseSensitive(final int columnIndex) {
+        return resultSetMetaData.isCaseSensitive(columnIndex);
+    }
+    
     /**
      * Get sharding encryptor.
      * 
diff --git a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/StreamQueryResult.java b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/StreamQueryResult.java
index ee8d6833be1..0163fc69f11 100644
--- a/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/StreamQueryResult.java
+++ b/sharding-core/sharding-core-execute/src/main/java/org/apache/shardingsphere/core/execute/sql/execute/result/StreamQueryResult.java
@@ -36,6 +36,7 @@ import java.util.Calendar;
  *
  * @author zhangliang
  * @author panjuan
+ * @author yangyi
  */
 public final class StreamQueryResult implements QueryResult {
     
@@ -139,6 +140,11 @@ public final class StreamQueryResult implements QueryResult {
         return resultSet.wasNull();
     }
     
+    @Override
+    public boolean isCaseSensitive(final int columnIndex) {
+        return metaData.isCaseSensitive(columnIndex);
+    }
+    
     @Override
     public int getColumnCount() {
         return metaData.getColumnCount();
diff --git a/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResultTest.java b/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResultTest.java
index 98b295b4e3e..45e6b048578 100644
--- a/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResultTest.java
+++ b/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/DistinctQueryResultTest.java
@@ -18,6 +18,7 @@
 package org.apache.shardingsphere.core.execute.sql.execute.result;
 
 import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Multimap;
 import lombok.SneakyThrows;
 import org.junit.Before;
@@ -61,6 +62,7 @@ public class DistinctQueryResultTest {
             when(queryResult.getColumnCount()).thenReturn(1);
             when(queryResult.getColumnLabel(1)).thenReturn("order_id");
             when(queryResult.getValue(1, Object.class)).thenReturn(10 * i);
+            when(queryResult.isCaseSensitive(1)).thenReturn(true);
             result.add(queryResult);
             result.add(queryResult);
         }
@@ -134,6 +136,11 @@ public class DistinctQueryResultTest {
         assertTrue(distinctQueryResult.wasNull());
     }
     
+    @Test
+    public void assertIsCaseSensitive() {
+        assertTrue(distinctQueryResult.isCaseSensitive(1));
+    }
+    
     @Test
     public void assertGetColumnCount() {
         assertThat(distinctQueryResult.getColumnCount(), is(1));
@@ -163,6 +170,12 @@ public class DistinctQueryResultTest {
         assertThat(distinctQueryResult.getColumnLabelAndIndexMap(), is(expected));
     }
     
+    @Test
+    public void assertGetColumnCaseSensitive() {
+        List<Boolean> expected = Lists.newArrayList(false, true);
+        assertThat(distinctQueryResult.getColumnCaseSensitive(), is(expected));
+    }
+    
     @Test
     public void assertGetResultData() {
         assertThat(distinctQueryResult.getResultData().next().getColumnValue(1), is((Object) 10));
diff --git a/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaDataTest.java b/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaDataTest.java
index aa02d1aec22..e3fa7d72944 100644
--- a/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaDataTest.java
+++ b/sharding-core/sharding-core-execute/src/test/java/org/apache/shardingsphere/core/execute/sql/execute/result/QueryResultMetaDataTest.java
@@ -32,6 +32,7 @@ import java.sql.SQLException;
 import java.util.Collections;
 
 import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -72,6 +73,7 @@ public class QueryResultMetaDataTest {
         when(result.getColumnName(anyInt())).thenReturn("column");
         when(result.getColumnLabel(anyInt())).thenReturn("label");
         when(result.getTableName(anyInt())).thenReturn("table");
+        when(result.isCaseSensitive(anyInt())).thenReturn(false);
         return result;
     }
     
@@ -95,6 +97,11 @@ public class QueryResultMetaDataTest {
         assertThat(queryResultMetaData.getColumnIndex("label"), is(1));
     }
     
+    @Test
+    public void assertIsCaseSensitive() {
+        assertFalse(queryResultMetaData.isCaseSensitive(1));
+    }
+    
     @Test
     public void assertGetShardingEncryptor() {
         assertThat(queryResultMetaData.getShardingEncryptor(1).get(), is(shardingEncryptor));
diff --git a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByMemoryMergedResult.java b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByMemoryMergedResult.java
index f1f29386bdb..af78132eea0 100644
--- a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByMemoryMergedResult.java
+++ b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByMemoryMergedResult.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.core.merge.dql.groupby;
 
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.apache.shardingsphere.core.execute.sql.execute.result.QueryResult;
 import org.apache.shardingsphere.core.merge.dql.common.MemoryMergedResult;
@@ -41,6 +42,7 @@ import java.util.Map.Entry;
  * Memory merged result for group by.
  *
  * @author zhangliang
+ * @author yangyi
  */
 public final class GroupByMemoryMergedResult extends MemoryMergedResult {
     
@@ -66,7 +68,8 @@ public final class GroupByMemoryMergedResult extends MemoryMergedResult {
             }
         }
         setAggregationValueToMemoryRow(dataMap, aggregationMap);
-        List<MemoryQueryResultRow> result = getMemoryResultSetRows(dataMap);
+        List<Boolean> valueCaseSensitive = queryResults.isEmpty() ? Collections.<Boolean>emptyList() : getValueCaseSensitive(queryResults.iterator().next());
+        List<MemoryQueryResultRow> result = getMemoryResultSetRows(dataMap, valueCaseSensitive);
         if (!result.isEmpty()) {
             setCurrentResultSetRow(result.get(0));
         }
@@ -118,9 +121,17 @@ public final class GroupByMemoryMergedResult extends MemoryMergedResult {
         }
     }
     
-    private List<MemoryQueryResultRow> getMemoryResultSetRows(final Map<GroupByValue, MemoryQueryResultRow> dataMap) {
+    private List<Boolean> getValueCaseSensitive(final QueryResult queryResult) throws SQLException {
+        List<Boolean> result = Lists.newArrayList(false);
+        for (int columnIndex = 1; columnIndex <= queryResult.getColumnCount(); columnIndex++) {
+            result.add(queryResult.isCaseSensitive(columnIndex));
+        }
+        return result;
+    }
+    
+    private List<MemoryQueryResultRow> getMemoryResultSetRows(final Map<GroupByValue, MemoryQueryResultRow> dataMap, final List<Boolean> valueCaseSensitive) {
         List<MemoryQueryResultRow> result = new ArrayList<>(dataMap.values());
-        Collections.sort(result, new GroupByRowComparator(optimizedStatement));
+        Collections.sort(result, new GroupByRowComparator(optimizedStatement, valueCaseSensitive));
         return result;
     }
     
diff --git a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparator.java b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparator.java
index 78e42f09090..dc1d50327cf 100644
--- a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparator.java
+++ b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparator.java
@@ -26,17 +26,21 @@ import org.apache.shardingsphere.core.optimize.statement.sharding.dml.select.ord
 
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.List;
 
 /**
  * Group by row comparator.
  *
  * @author zhangliang
+ * @author yangyi
  */
 @RequiredArgsConstructor
 public final class GroupByRowComparator implements Comparator<MemoryQueryResultRow> {
     
     private final ShardingSelectOptimizedStatement optimizedStatement;
     
+    private final List<Boolean> valueCaseSensitive;
+    
     @Override
     public int compare(final MemoryQueryResultRow o1, final MemoryQueryResultRow o2) {
         if (!optimizedStatement.getOrderBy().getItems().isEmpty()) {
@@ -51,7 +55,8 @@ public final class GroupByRowComparator implements Comparator<MemoryQueryResultR
             Preconditions.checkState(null == orderValue1 || orderValue1 instanceof Comparable, "Order by value must implements Comparable");
             Object orderValue2 = o2.getCell(each.getIndex());
             Preconditions.checkState(null == orderValue2 || orderValue2 instanceof Comparable, "Order by value must implements Comparable");
-            int result = CompareUtil.compareTo((Comparable) orderValue1, (Comparable) orderValue2, each.getSegment().getOrderDirection(), each.getSegment().getNullOrderDirection());
+            int result = CompareUtil.compareTo((Comparable) orderValue1, (Comparable) orderValue2, each.getSegment().getOrderDirection(),
+                each.getSegment().getNullOrderDirection(), valueCaseSensitive.get(each.getIndex()));
             if (0 != result) {
                 return result;
             }
diff --git a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtil.java b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtil.java
index 6157cf8f740..85a2322d013 100644
--- a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtil.java
+++ b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtil.java
@@ -25,6 +25,7 @@ import org.apache.shardingsphere.core.constant.OrderDirection;
  * Compare util.
  *
  * @author zhangliang
+ * @author yangyi
  */
 @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
 public final class CompareUtil {
@@ -36,10 +37,11 @@ public final class CompareUtil {
      * @param otherValue other value
      * @param orderDirection order direction 
      * @param nullOrderDirection order direction for null value
+     * @param caseSensitive case sensitive
      * @return compare result
      */
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static int compareTo(final Comparable thisValue, final Comparable otherValue, final OrderDirection orderDirection, final OrderDirection nullOrderDirection) {
+    public static int compareTo(final Comparable thisValue, final Comparable otherValue, final OrderDirection orderDirection, final OrderDirection nullOrderDirection, final boolean caseSensitive) {
         if (null == thisValue && null == otherValue) {
             return 0;
         }
@@ -49,6 +51,14 @@ public final class CompareUtil {
         if (null == otherValue) {
             return orderDirection == nullOrderDirection ? 1 : -1;
         }
+        if (!caseSensitive && thisValue instanceof String && otherValue instanceof String) {
+            return compareToCaseInsensitiveString((String) thisValue, (String) otherValue, orderDirection);
+        }
         return OrderDirection.ASC == orderDirection ? thisValue.compareTo(otherValue) : -thisValue.compareTo(otherValue);
     }
+    
+    private static int compareToCaseInsensitiveString(final String thisValue, final String otherValue, final OrderDirection orderDirection) {
+        int result = thisValue.toUpperCase().compareTo(otherValue.toUpperCase());
+        return OrderDirection.ASC == orderDirection ? result : -result;
+    }
 }
diff --git a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValue.java b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValue.java
index 182d0dfd288..75307dc3c9a 100644
--- a/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValue.java
+++ b/sharding-core/sharding-core-merge/src/main/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValue.java
@@ -19,7 +19,7 @@ package org.apache.shardingsphere.core.merge.dql.orderby;
 
 import com.google.common.base.Preconditions;
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
 import org.apache.shardingsphere.core.execute.sql.execute.result.QueryResult;
 import org.apache.shardingsphere.core.optimize.statement.sharding.dml.select.orderby.OrderByItem;
 
@@ -33,8 +33,8 @@ import java.util.List;
  * Order by value.
  * 
  * @author zhangliang
+ * @author yangyi
  */
-@RequiredArgsConstructor
 public final class OrderByValue implements Comparable<OrderByValue> {
     
     @Getter
@@ -42,8 +42,25 @@ public final class OrderByValue implements Comparable<OrderByValue> {
     
     private final Collection<OrderByItem> orderByItems;
     
+    private final List<Boolean> orderValuesCaseSensitive;
+    
     private List<Comparable<?>> orderValues;
     
+    public OrderByValue(final QueryResult queryResult, final Collection<OrderByItem> orderByItems) {
+        this.queryResult = queryResult;
+        this.orderByItems = orderByItems;
+        this.orderValuesCaseSensitive = getOrderValuesCaseSensitive();
+    }
+    
+    @SneakyThrows
+    private List<Boolean> getOrderValuesCaseSensitive() {
+        List<Boolean> result = new ArrayList<>(orderByItems.size());
+        for (OrderByItem each : orderByItems) {
+            result.add(queryResult.isCaseSensitive(each.getIndex()));
+        }
+        return result;
+    }
+    
     /**
      * iterate next data.
      *
@@ -70,7 +87,8 @@ public final class OrderByValue implements Comparable<OrderByValue> {
     public int compareTo(final OrderByValue o) {
         int i = 0;
         for (OrderByItem each : orderByItems) {
-            int result = CompareUtil.compareTo(orderValues.get(i), o.orderValues.get(i), each.getSegment().getOrderDirection(), each.getSegment().getNullOrderDirection());
+            int result = CompareUtil.compareTo(orderValues.get(i), o.orderValues.get(i), each.getSegment().getOrderDirection(),
+                each.getSegment().getNullOrderDirection(), orderValuesCaseSensitive.get(i));
             if (0 != result) {
                 return result;
             }
diff --git a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/DQLMergeEngineTest.java b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/DQLMergeEngineTest.java
index b40e8290262..402b317b421 100644
--- a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/DQLMergeEngineTest.java
+++ b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/DQLMergeEngineTest.java
@@ -80,13 +80,20 @@ public final class DQLMergeEngineTest {
         when(resultSetMetaData.getColumnCount()).thenReturn(1);
         when(resultSetMetaData.getColumnLabel(1)).thenReturn("count(*)");
         singleQueryResult = Collections.<QueryResult>singletonList(new TestQueryResult(resultSet));
-        List<ResultSet> resultSets = Lists.newArrayList(resultSet, mock(ResultSet.class), mock(ResultSet.class), mock(ResultSet.class));
+        List<ResultSet> resultSets = Lists.newArrayList(resultSet, mockResultSet(), mockResultSet(), mockResultSet());
         queryResults = new ArrayList<>(resultSets.size());
         for (ResultSet each : resultSets) {
             queryResults.add(new TestQueryResult(each));
         }
     }
     
+    private ResultSet mockResultSet() throws SQLException {
+        ResultSet result = mock(ResultSet.class);
+        ResultSetMetaData resultSetMetaData = mock(ResultSetMetaData.class);
+        when(result.getMetaData()).thenReturn(resultSetMetaData);
+        return result;
+    }
+    
     @Test
     public void assertBuildIteratorStreamMergedResult() throws SQLException {
         OptimizedStatement optimizedStatement = new ShardingSelectOptimizedStatement(new SelectStatement(), Collections.<ShardingCondition>emptyList(), new AndCondition(),
diff --git a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparatorTest.java b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparatorTest.java
index 3a220a51f09..c0f3d69ca51 100644
--- a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparatorTest.java
+++ b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/groupby/GroupByRowComparatorTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.core.merge.dql.groupby;
 
+import com.google.common.collect.Lists;
 import org.apache.shardingsphere.core.constant.OrderDirection;
 import org.apache.shardingsphere.core.execute.sql.execute.result.QueryResult;
 import org.apache.shardingsphere.core.merge.dql.common.MemoryQueryResultRow;
@@ -39,6 +40,7 @@ import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
@@ -48,6 +50,8 @@ import static org.mockito.Mockito.when;
 
 public final class GroupByRowComparatorTest {
     
+    private final List<Boolean> caseSensitives = Lists.newArrayList(false, false, false);
+    
     @Test
     public void assertCompareToForAscWithOrderByItems() throws SQLException {
         ShardingSelectOptimizedStatement optimizedStatement = new ShardingSelectOptimizedStatement(
@@ -59,7 +63,7 @@ public final class GroupByRowComparatorTest {
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 1, OrderDirection.ASC, OrderDirection.ASC)),
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 2, OrderDirection.ASC, OrderDirection.ASC))), false),
                 new SelectItems(Collections.<SelectItem>emptyList(), false, 0), new Pagination(null, null, Collections.emptyList()));
-        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement);
+        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement, caseSensitives);
         MemoryQueryResultRow o1 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         MemoryQueryResultRow o2 = new MemoryQueryResultRow(mockQueryResult("3", "4"));
         assertTrue(groupByRowComparator.compare(o1, o2) < 0);
@@ -76,7 +80,7 @@ public final class GroupByRowComparatorTest {
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 1, OrderDirection.DESC, OrderDirection.ASC)),
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 2, OrderDirection.DESC, OrderDirection.ASC))), false),
                 new SelectItems(Collections.<SelectItem>emptyList(), false, 0), new Pagination(null, null, Collections.emptyList()));
-        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement);
+        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement, caseSensitives);
         MemoryQueryResultRow o1 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         MemoryQueryResultRow o2 = new MemoryQueryResultRow(mockQueryResult("3", "4"));
         assertTrue(groupByRowComparator.compare(o1, o2) > 0);
@@ -93,7 +97,7 @@ public final class GroupByRowComparatorTest {
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 1, OrderDirection.ASC, OrderDirection.ASC)),
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 2, OrderDirection.DESC, OrderDirection.ASC))), false),
                 new SelectItems(Collections.<SelectItem>emptyList(), false, 0), new Pagination(null, null, Collections.emptyList()));
-        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement);
+        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement, caseSensitives);
         MemoryQueryResultRow o1 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         MemoryQueryResultRow o2 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         assertThat(groupByRowComparator.compare(o1, o2), is(0));
@@ -107,7 +111,7 @@ public final class GroupByRowComparatorTest {
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 1, OrderDirection.ASC, OrderDirection.ASC)),
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 2, OrderDirection.ASC, OrderDirection.ASC))), 0), new OrderBy(Collections.<OrderByItem>emptyList(), false),
                 new SelectItems(Collections.<SelectItem>emptyList(), false, 0), new Pagination(null, null, Collections.emptyList()));
-        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement);
+        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement, caseSensitives);
         MemoryQueryResultRow o1 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         MemoryQueryResultRow o2 = new MemoryQueryResultRow(mockQueryResult("3", "4"));
         assertTrue(groupByRowComparator.compare(o1, o2) < 0);
@@ -121,7 +125,7 @@ public final class GroupByRowComparatorTest {
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 1, OrderDirection.DESC, OrderDirection.ASC)),
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 2, OrderDirection.DESC, OrderDirection.ASC))), 0), new OrderBy(Collections.<OrderByItem>emptyList(), false),
                 new SelectItems(Collections.<SelectItem>emptyList(), false, 0), new Pagination(null, null, Collections.emptyList()));
-        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement);
+        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement, caseSensitives);
         MemoryQueryResultRow o1 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         MemoryQueryResultRow o2 = new MemoryQueryResultRow(mockQueryResult("3", "4"));
         assertTrue(groupByRowComparator.compare(o1, o2) > 0);
@@ -135,7 +139,7 @@ public final class GroupByRowComparatorTest {
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 1, OrderDirection.ASC, OrderDirection.ASC)),
                         createOrderByItem(new IndexOrderByItemSegment(0, 0, 2, OrderDirection.DESC, OrderDirection.ASC))), 0), new OrderBy(Collections.<OrderByItem>emptyList(), false),
                 new SelectItems(Collections.<SelectItem>emptyList(), false, 0), new Pagination(null, null, Collections.emptyList()));
-        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement);
+        GroupByRowComparator groupByRowComparator = new GroupByRowComparator(optimizedStatement, caseSensitives);
         MemoryQueryResultRow o1 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         MemoryQueryResultRow o2 = new MemoryQueryResultRow(mockQueryResult("1", "2"));
         assertThat(groupByRowComparator.compare(o1, o2), is(0));
diff --git a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtilTest.java b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtilTest.java
index b61457016e5..4c0d1003432 100644
--- a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtilTest.java
+++ b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/CompareUtilTest.java
@@ -25,58 +25,70 @@ import static org.junit.Assert.assertThat;
 
 public final class CompareUtilTest {
     
+    private final boolean caseSensitive = true;
+    
     @Test
     public void assertCompareToWhenBothNull() {
-        assertThat(CompareUtil.compareTo(null, null, OrderDirection.DESC, OrderDirection.ASC), is(0));
+        assertThat(CompareUtil.compareTo(null, null, OrderDirection.DESC, OrderDirection.ASC, caseSensitive), is(0));
     }
     
     @Test
     public void assertCompareToWhenFirstValueIsNullForOrderByAscAndNullOrderByAsc() {
-        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.ASC, OrderDirection.ASC), is(-1));
+        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.ASC, OrderDirection.ASC, caseSensitive), is(-1));
     }
     
     @Test
     public void assertCompareToWhenFirstValueIsNullForOrderByAscAndNullOrderByDesc() {
-        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.ASC, OrderDirection.DESC), is(1));
+        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.ASC, OrderDirection.DESC, caseSensitive), is(1));
     }
     
     @Test
     public void assertCompareToWhenFirstValueIsNullForOrderByDescAndNullOrderByAsc() {
-        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.DESC, OrderDirection.ASC), is(1));
+        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.DESC, OrderDirection.ASC, caseSensitive), is(1));
     }
     
     @Test
     public void assertCompareToWhenFirstValueIsNullForOrderByDescAndNullOrderByDesc() {
-        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.DESC, OrderDirection.DESC), is(-1));
+        assertThat(CompareUtil.compareTo(null, 1, OrderDirection.DESC, OrderDirection.DESC, caseSensitive), is(-1));
     }
     
     @Test
     public void assertCompareToWhenSecondValueIsNullForOrderByAscAndNullOrderByAsc() {
-        assertThat(CompareUtil.compareTo(1, null, OrderDirection.ASC, OrderDirection.ASC), is(1));
+        assertThat(CompareUtil.compareTo(1, null, OrderDirection.ASC, OrderDirection.ASC, caseSensitive), is(1));
     }
     
     @Test
     public void assertCompareToWhenSecondValueIsNullForOrderByAscAndNullOrderByDesc() {
-        assertThat(CompareUtil.compareTo(1, null, OrderDirection.ASC, OrderDirection.DESC), is(-1));
+        assertThat(CompareUtil.compareTo(1, null, OrderDirection.ASC, OrderDirection.DESC, caseSensitive), is(-1));
     }
     
     @Test
     public void assertCompareToWhenSecondValueIsNullForOrderByDescAndNullOrderByAsc() {
-        assertThat(CompareUtil.compareTo(1, null, OrderDirection.DESC, OrderDirection.ASC), is(-1));
+        assertThat(CompareUtil.compareTo(1, null, OrderDirection.DESC, OrderDirection.ASC, caseSensitive), is(-1));
     }
     
     @Test
     public void assertCompareToWhenSecondValueIsNullForOrderByDescAndNullOrderByDesc() {
-        assertThat(CompareUtil.compareTo(1, null, OrderDirection.DESC, OrderDirection.DESC), is(1));
+        assertThat(CompareUtil.compareTo(1, null, OrderDirection.DESC, OrderDirection.DESC, caseSensitive), is(1));
     }
     
     @Test
     public void assertCompareToWhenAsc() {
-        assertThat(CompareUtil.compareTo(1, 2, OrderDirection.ASC, OrderDirection.ASC), is(-1));
+        assertThat(CompareUtil.compareTo(1, 2, OrderDirection.ASC, OrderDirection.ASC, caseSensitive), is(-1));
     }
     
     @Test
     public void assertCompareToWhenDesc() {
-        assertThat(CompareUtil.compareTo(1, 2, OrderDirection.DESC, OrderDirection.ASC), is(1));
+        assertThat(CompareUtil.compareTo(1, 2, OrderDirection.DESC, OrderDirection.ASC, caseSensitive), is(1));
+    }
+    
+    @Test
+    public void assetCompareToStringWithCaseSensitive() {
+        assertThat(CompareUtil.compareTo("A", "a", OrderDirection.DESC, OrderDirection.ASC, caseSensitive), is(32));
+    }
+    
+    @Test
+    public void assetCompareToStringWithCaseInsensitive() {
+        assertThat(CompareUtil.compareTo("A", "a", OrderDirection.DESC, OrderDirection.ASC, !caseSensitive), is(0));
     }
 }
diff --git a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByStreamMergedResultTest.java b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByStreamMergedResultTest.java
index 1dd6ba63402..813ca0850d4 100644
--- a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByStreamMergedResultTest.java
+++ b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByStreamMergedResultTest.java
@@ -63,11 +63,8 @@ public final class OrderByStreamMergedResultTest {
     
     @Before
     public void setUp() throws SQLException {
-        ResultSet resultSet = mock(ResultSet.class);
-        ResultSetMetaData resultSetMetaData = mock(ResultSetMetaData.class);
-        when(resultSet.getMetaData()).thenReturn(resultSetMetaData);
         queryResults = Lists.<QueryResult>newArrayList(
-                new TestQueryResult(resultSet), new TestQueryResult(mock(ResultSet.class)), new TestQueryResult(mock(ResultSet.class)));
+                new TestQueryResult(mockResultSet()), new TestQueryResult(mockResultSet()), new TestQueryResult(mockResultSet()));
         OptimizedStatement optimizedStatement = new ShardingSelectOptimizedStatement(
                 new SelectStatement(), Collections.<ShardingCondition>emptyList(), new AndCondition(), new GroupBy(Collections.<OrderByItem>emptyList(), 0), 
                 new OrderBy(Collections.singletonList(new OrderByItem(new IndexOrderByItemSegment(0, 0, 1, OrderDirection.ASC, OrderDirection.ASC))), false), 
@@ -75,6 +72,13 @@ public final class OrderByStreamMergedResultTest {
         routeResult = new SQLRouteResult(optimizedStatement);
     }
     
+    private ResultSet mockResultSet() throws SQLException {
+        ResultSet result = mock(ResultSet.class);
+        ResultSetMetaData resultSetMetaData = mock(ResultSetMetaData.class);
+        when(result.getMetaData()).thenReturn(resultSetMetaData);
+        return result;
+    }
+    
     @Test
     public void assertNextForResultSetsAllEmpty() throws SQLException {
         mergeEngine = new DQLMergeEngine(DatabaseTypes.getActualDatabaseType("MySQL"), routeResult, queryResults);
@@ -123,4 +127,52 @@ public final class OrderByStreamMergedResultTest {
         assertThat(actual.getValue(1, Object.class).toString(), is("4"));
         assertFalse(actual.next());
     }
+    
+    @Test
+    public void assertNextForCaseSensitive() throws SQLException {
+        when(queryResults.get(0).next()).thenReturn(true, false);
+        when(queryResults.get(0).isCaseSensitive(1)).thenReturn(true);
+        when(queryResults.get(0).getValue(1, Object.class)).thenReturn("b");
+        when(queryResults.get(1).next()).thenReturn(true, true, false);
+        when(queryResults.get(1).isCaseSensitive(1)).thenReturn(true);
+        when(queryResults.get(1).getValue(1, Object.class)).thenReturn("B", "B", "a", "a");
+        when(queryResults.get(2).next()).thenReturn(true, false);
+        when(queryResults.get(2).isCaseSensitive(1)).thenReturn(true);
+        when(queryResults.get(2).getValue(1, Object.class)).thenReturn("A");
+        mergeEngine = new DQLMergeEngine(DatabaseTypes.getActualDatabaseType("MySQL"), routeResult, queryResults);
+        MergedResult actual = mergeEngine.merge();
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("A"));
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("B"));
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("a"));
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("b"));
+        assertFalse(actual.next());
+    }
+    
+    @Test
+    public void assertNextForCaseInsensitive() throws SQLException {
+        when(queryResults.get(0).next()).thenReturn(true, false);
+        when(queryResults.get(0).isCaseSensitive(1)).thenReturn(false);
+        when(queryResults.get(0).getValue(1, Object.class)).thenReturn("b");
+        when(queryResults.get(1).next()).thenReturn(true, true, false);
+        when(queryResults.get(1).isCaseSensitive(1)).thenReturn(false);
+        when(queryResults.get(1).getValue(1, Object.class)).thenReturn("a", "a", "B", "B");
+        when(queryResults.get(2).next()).thenReturn(true, false);
+        when(queryResults.get(2).isCaseSensitive(1)).thenReturn(false);
+        when(queryResults.get(2).getValue(1, Object.class)).thenReturn("A");
+        mergeEngine = new DQLMergeEngine(DatabaseTypes.getActualDatabaseType("MySQL"), routeResult, queryResults);
+        MergedResult actual = mergeEngine.merge();
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("a"));
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("A"));
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("B"));
+        assertTrue(actual.next());
+        assertThat(actual.getValue(1, Object.class).toString(), is("b"));
+        assertFalse(actual.next());
+    }
 }
diff --git a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValueTest.java b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValueTest.java
index d61aa78c441..5b47c89ab7c 100644
--- a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValueTest.java
+++ b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/dql/orderby/OrderByValueTest.java
@@ -28,6 +28,7 @@ import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
 import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.util.Arrays;
 
@@ -46,12 +47,19 @@ public final class OrderByValueTest {
     @Mock
     private ResultSet resultSet2;
     
+    @Mock
+    private ResultSetMetaData resultSetMetaData;
+    
     @Before
     public void setUp() throws SQLException {
         when(resultSet1.next()).thenReturn(true, false);
         when(resultSet2.next()).thenReturn(true, false);
         when(resultSet1.getObject(1)).thenReturn("1");
         when(resultSet1.getObject(2)).thenReturn("2");
+        when(resultSet1.getMetaData()).thenReturn(resultSetMetaData);
+        when(resultSet2.getMetaData()).thenReturn(resultSetMetaData);
+        when(resultSetMetaData.isCaseSensitive(1)).thenReturn(false);
+        when(resultSetMetaData.isCaseSensitive(1)).thenReturn(true);
     }
     
     @Test
diff --git a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/fixture/TestQueryResult.java b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/fixture/TestQueryResult.java
index ed9dbaf23b5..f7583dd585c 100644
--- a/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/fixture/TestQueryResult.java
+++ b/sharding-core/sharding-core-merge/src/test/java/org/apache/shardingsphere/core/merge/fixture/TestQueryResult.java
@@ -201,6 +201,11 @@ public final class TestQueryResult implements QueryResult {
         return resultSet.wasNull();
     }
     
+    @Override
+    public boolean isCaseSensitive(final int columnIndex) throws SQLException {
+        return resultSet.getMetaData().isCaseSensitive(columnIndex);
+    }
+    
     @Override
     public int getColumnCount() throws SQLException {
         return resultSet.getMetaData().getColumnCount();