Index: src/wp-includes/user.php
===================================================================
--- src/wp-includes/user.php	(revision 28157)
+++ src/wp-includes/user.php	(working copy)
@@ -666,7 +666,26 @@
 			}

 			if ( empty( $qv['meta_query'] ) || ! in_array( $cap_meta_query, $qv['meta_query'], true ) ) {
-				$qv['meta_query'][] = $cap_meta_query;
+				// The cap meta query should always be an AND relation, so if there
+				// is a main meta query and it is using OR relations, we need to
+				// handle the cap meta query separate.
+				if ( ! empty( $qv['meta_query']['relation'] ) && 'OR' == strtoupper( $qv['meta_query']['relation'] ) ) {
+					$meta_query = new WP_Meta_Query();
+					$meta_query->parse_query_vars( array( 'meta_query' => array( $cap_meta_query ) ) );
+
+					if ( ! empty( $meta_query->queries ) ) {
+						$clauses = $meta_query->get_sql( 'user', $wpdb->users, 'ID', $this );
+
+						$this->query_from .= str_replace(
+							array( "$wpdb->usermeta ON",           "$wpdb->usermeta." ),
+							array( "$wpdb->usermeta AS cap_mt ON", 'cap_mt.'          ),
+							$clauses['join']
+						);
+						$this->query_where .= str_replace( "$wpdb->usermeta", 'cap_mt', $clauses['where'] );
+					}
+				} else {
+					$qv['meta_query'][] = $cap_meta_query;
+				}
 			}
 		}

Index: tests/phpunit/tests/user/query.php
===================================================================
--- tests/phpunit/tests/user/query.php	(revision 28157)
+++ tests/phpunit/tests/user/query.php	(working copy)
@@ -137,4 +137,97 @@
 		$query->prepare_query();
 		$this->assertEquals( $_query_vars, $query->query_vars );
 	}
+
+	/**
+	 * Test 'NOT EXISTS' user meta query compare with OR relations.
+	 *
+	 * @ticket 23849
+	 */
+	public function test_meta_query_compare_not_exists() {
+
+		// Set the 'test_meta_not_exists' key for just the first user.
+		update_user_meta( $this->user_id, 'test_meta_not_exists', 1 );
+
+		// A meta query for the users with that key should return one user.
+		$query_1 = new WP_User_Query(
+			array(
+				'meta_query' => array(
+					array(
+						'key' => 'test_meta_not_exists',
+						'compare' => 'EXISTS',
+					),
+				),
+			)
+		);
+
+		$this->assertEquals( 1, $query_1->get_total() );
+
+		// Run the not exists query with AND relation.
+		$query_2 = new WP_User_Query(
+			array(
+				'meta_query' => array(
+					'relation' => 'AND',
+					array(
+						'key' => 'test_meta_not_exists',
+						'compare' => 'NOT EXISTS',
+					),
+				),
+			)
+		);
+
+		// We should find one user (the current user which won't have the meta key).
+		$this->assertEquals( 1, $query_2->get_total() );
+
+		// Now run the not exists query with OR relation.
+		$query_3 = new WP_User_Query(
+			array(
+				'meta_query' => array(
+					'relation' => 'OR',
+					array(
+						'key' => 'test_meta_not_exists',
+						'compare' => 'NOT EXISTS',
+					),
+				),
+			)
+		);
+
+		// We should find one user.
+		$this->assertEquals( 1, $query_3->get_total() );
+	}
+
+	/**
+	 * Test using user meta query when specifying a role.
+	 *
+	 * @ticket 23849
+	 */
+	public function test_meta_query_with_role() {
+
+		$user_id = $this->factory->user->create( array( 'role' => 'author' ) );
+
+		update_user_meta( $user_id, 'test_meta_not_exists', 'off' );
+
+		$args = array(
+			'role'		=> 'Author',
+			'number'	=> 100,
+			'offset'	=> 0,
+			'meta_query' => array(
+				'relation' => 'OR',
+				array(
+					'key'		=> 'test_meta_not_exists',
+					'compare'	=> 'NOT EXISTS',
+				),
+				array(
+					'key'		=> 'test_meta_not_exists',
+					'value'		=> 'off',
+					'compare'	=> '!=',
+				),
+			),
+		);
+
+		$this->assertEquals( 1, ( new WP_User_Query( $args ) )->get_total() );
+
+		update_user_meta( $user_id, 'test_meta_not_exists', 'on' );
+
+		$this->assertEquals( 2, ( new WP_User_Query( $args ) )->get_total() );
+	}
 }
