Index: src/wp-includes/class-wp-tax-query.php
===================================================================
--- src/wp-includes/class-wp-tax-query.php	(revision 37651)
+++ src/wp-includes/class-wp-tax-query.php	(working copy)
@@ -600,22 +600,43 @@
 	 * @global wpdb $wpdb The WordPress database abstraction object.
 	 *
 	 * @param array  $query           The single query. Passed by reference.
-	 * @param string $resulting_field The resulting field. Accepts 'slug', 'name', 'term_taxonomy_id',
+	 * @param string $fields The resulting field. Accepts 'slug', 'name', 'term_taxonomy_id',
 	 *                                or 'term_id'. Default 'term_id'.
 	 */
-	public function transform_query( &$query, $resulting_field ) {
+	public function transform_query( &$query, $fields ) {
 		global $wpdb;
 
-		if ( empty( $query['terms'] ) )
+		if ( empty( $query['terms'] ) ) {
 			return;
+		}
 
-		if ( $query['field'] == $resulting_field )
+		if ( $query['field'] == $fields ) {
 			return;
+		}
 
-		$resulting_field = sanitize_key( $resulting_field );
+		$fields = sanitize_key( $fields );
 
+		$args = array(
+			'taxonomy'               => $query['taxonomy'],
+			'update_term_meta_cache' => false,
+			'hide_empty'             => false,
+			'fields'                 => $fields
+		);
+
 		switch ( $query['field'] ) {
 			case 'slug':
+				foreach ( $query['terms'] as &$term ) {
+					/*
+					 * 0 is the $term_id parameter. We don't have a term ID yet, but it doesn't
+					 * matter because `sanitize_term_field()` ignores the $term_id param when the
+					 * context is 'db'.
+					 */
+					$term = "'" . esc_sql( sanitize_term_field( $query['field'], $term, 0, $query['taxonomy'], 'db' ) ) . "'";
+				}
+
+				$terms        = implode( ",", $query['terms'] );
+				$args['slug'] = $terms;
+				break;
 			case 'name':
 				foreach ( $query['terms'] as &$term ) {
 					/*
@@ -626,40 +647,31 @@
 					$term = "'" . esc_sql( sanitize_term_field( $query['field'], $term, 0, $query['taxonomy'], 'db' ) ) . "'";
 				}
 
-				$terms = implode( ",", $query['terms'] );
-
-				$terms = $wpdb->get_col( "
-					SELECT $wpdb->term_taxonomy.$resulting_field
-					FROM $wpdb->term_taxonomy
-					INNER JOIN $wpdb->terms USING (term_id)
-					WHERE taxonomy = '{$query['taxonomy']}'
-					AND $wpdb->terms.{$query['field']} IN ($terms)
-				" );
+				$terms        = implode( ",", $query['terms'] );
+				$args['name'] = $terms;
 				break;
 			case 'term_taxonomy_id':
-				$terms = implode( ',', array_map( 'intval', $query['terms'] ) );
-				$terms = $wpdb->get_col( "
-					SELECT $resulting_field
-					FROM $wpdb->term_taxonomy
-					WHERE term_taxonomy_id IN ($terms)
-				" );
+				$terms                    = implode( ',', array_map( 'intval', $query['terms'] ) );
+				$args['term_taxonomy_id'] = $terms;
 				break;
 			default:
-				$terms = implode( ',', array_map( 'intval', $query['terms'] ) );
-				$terms = $wpdb->get_col( "
-					SELECT $resulting_field
-					FROM $wpdb->term_taxonomy
-					WHERE taxonomy = '{$query['taxonomy']}'
-					AND term_id IN ($terms)
-				" );
+				$terms           = implode( ',', array_map( 'intval', $query['terms'] ) );
+				$args['include'] = $terms;
 		}
+		$args['number']  = count( $terms );
+		$term_list = get_terms( $args );
 
-		if ( 'AND' == $query['operator'] && count( $terms ) < count( $query['terms'] ) ) {
+		if ( is_wp_error( $term_list ) ) {
+			$query = $term_list;
+			return;
+		}
+
+		if ( 'AND' == $query['operator'] && count( $term_list ) < count( $query['terms'] ) ) {
 			$query = new WP_Error( 'Inexistent terms' );
 			return;
 		}
 
-		$query['terms'] = $terms;
-		$query['field'] = $resulting_field;
+		$query['terms'] = $term_list;
+		$query['field'] = $fields;
 	}
 }
Index: src/wp-includes/class-wp-term-query.php
===================================================================
--- src/wp-includes/class-wp-term-query.php	(revision 37651)
+++ src/wp-includes/class-wp-term-query.php	(working copy)
@@ -183,6 +183,7 @@
 			'count'                  => false,
 			'name'                   => '',
 			'slug'                   => '',
+			'term_taxonomy_id'       => '',
 			'hierarchical'           => true,
 			'search'                 => '',
 			'name__like'             => '',
@@ -473,6 +474,16 @@
 			}
 		}
 
+		if ( ! empty( $args['term_taxonomy_id'] ) ) {
+			if ( is_array( $args['term_taxonomy_id'] ) ) {
+				$term_taxonomy_id = array_map( 'intval', $args['term_taxonomy_id'] );
+				$this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id IN ('" . implode( "', '", $term_taxonomy_id ) . "')";
+			} else {
+				$term_taxonomy_id = intval( $args['term_taxonomy_id'] );
+				$this->sql_clauses['where']['term_taxonomy_id'] = "tt.term_taxonomy_id = '$term_taxonomy_id'";
+			}
+		}
+
 		if ( ! empty( $args['name__like'] ) ) {
 			$this->sql_clauses['where']['name__like'] = $wpdb->prepare( "t.name LIKE %s", '%' . $wpdb->esc_like( $args['name__like'] ) . '%' );
 		}
@@ -541,6 +552,9 @@
 			case 'names':
 				$selects = array( 't.term_id', 'tt.parent', 'tt.count', 't.name', 'tt.taxonomy' );
 				break;
+			case 'term_taxonomy_id':
+				$selects = array( 't.term_id', 'tt.parent', 'tt.count', 'tt.term_taxonomy_id', 'tt.taxonomy' );
+				break;
 			case 'count':
 				$orderby = '';
 				$order = '';
@@ -692,8 +706,12 @@
 			foreach ( $terms as $term ) {
 				$_terms[] = $term->term_id;
 			}
-		} elseif ( 'names' == $_fields ) {
+		} elseif ( 'term_taxonomy_id' == $_fields ) {
 			foreach ( $terms as $term ) {
+				$_terms[] = $term->term_taxonomy_id;
+			}
+		}elseif ( 'names' == $_fields ) {
+			foreach ( $terms as $term ) {
 				$_terms[] = $term->name;
 			}
 		} elseif ( 'id=>name' == $_fields ) {
