Index: meta.php
===================================================================
--- meta.php	(revision 31261)
+++ meta.php	(working copy)
@@ -932,6 +932,14 @@
 	 * @var array
 	 */
 	protected $table_aliases = array();
+	
+	/**
+	 * A flat list of ORDER BY clauses with aliases as the keys.
+	 *
+	 * @since 4.2.0
+	 * @var array
+	 */
+	public $orderby_clauses = array();
 
 	/**
 	 * Constructor.
@@ -1351,8 +1359,12 @@
 		// We prefer to avoid joins if possible. Look for an existing join compatible with this clause.
 		$alias = $this->find_compatible_table_alias( $clause, $parent_query );
 		if ( false === $alias ) {
-			$i = count( $this->table_aliases );
-			$alias = $i ? 'mt' . $i : $this->meta_table;
+			if( empty( $clause['alias'] ) ){
+				$i = count( $this->table_aliases );
+				$alias = $i ? 'mt' . $i : $this->meta_table;
+			} else {
+				$alias = $clause['alias'];	
+			}
 
 			// JOIN clauses for NOT EXISTS have their own syntax.
 			if ( 'NOT EXISTS' === $meta_compare ) {
@@ -1373,6 +1385,14 @@
 
 		// Save the alias to this clause, for future siblings to find.
 		$clause['alias'] = $alias;
+		
+		//Build the ORDER BY clause
+		if ( ! empty( $primary_meta_query['type'] ) ) {
+			$meta_type = $this->meta_query->get_cast_for_type( $clause['type'] );
+			$this->orderby_clauses[$alias] = "CAST($alias.meta_value AS {$meta_type})";
+		} else {
+			$this->orderby_clauses[$alias] = "$alias.meta_value";
+		}
 
 		// Next, build the WHERE clause.
 
Index: query.php
===================================================================
--- query.php	(revision 31261)
+++ query.php	(working copy)
@@ -2230,6 +2230,8 @@
 			'post_parent', 'post_type', 'name', 'author', 'date', 'title', 'modified',
 			'parent', 'type', 'ID', 'menu_order', 'comment_count', 'rand',
 		);
+		
+		$allowed_keys = apply_filters( 'allowed_orderby_keys', $allowed_keys );
 
 		$primary_meta_key = '';
 		$primary_meta_query = false;
@@ -2244,6 +2246,10 @@
 			$allowed_keys[] = 'meta_value';
 			$allowed_keys[] = 'meta_value_num';
 		}
+		
+		if ( ! empty( $this->meta_query->table_aliases ) ) {
+			$aliases = (array) $this->meta_query->table_aliases;
+		}
 
 		if ( ! in_array( $orderby, $allowed_keys ) ) {
 			return false;
@@ -2260,29 +2266,32 @@
 			case 'ID':
 			case 'menu_order':
 			case 'comment_count':
-				$orderby = "$wpdb->posts.{$orderby}";
+				$orderby_clause = "$wpdb->posts.{$orderby}";
 				break;
 			case 'rand':
-				$orderby = 'RAND()';
+				$orderby_clause = 'RAND()';
 				break;
 			case $primary_meta_key:
 			case 'meta_value':
 				if ( ! empty( $primary_meta_query['type'] ) ) {
 					$sql_type = $this->meta_query->get_cast_for_type( $primary_meta_query['type'] );
-					$orderby = "CAST($wpdb->postmeta.meta_value AS {$sql_type})";
+					$orderby_clause = "CAST($wpdb->postmeta.meta_value AS {$sql_type})";
 				} else {
-					$orderby = "$wpdb->postmeta.meta_value";
+					$orderby_clause = "$wpdb->postmeta.meta_value";
 				}
 				break;
 			case 'meta_value_num':
-				$orderby = "$wpdb->postmeta.meta_value+0";
+				$orderby_clause = "$wpdb->postmeta.meta_value+0";
 				break;
+			case array_key_exists( $orderby, $this->meta_query->orderby_clauses ):
+				$orderby_clause = $this->meta_query->orderby_clauses[$orderby];
+				break;
 			default:
-				$orderby = "$wpdb->posts.post_" . $orderby;
+				$orderby_clause = "$wpdb->posts.post_" . $orderby;
 				break;
 		}
-
-		return $orderby;
+		
+		return apply_filters( 'parse_orderby', $orderby_clause, $orderby );
 	}
 
 	/**
