From BuddyPress Real Names,
how to filter members alphabetically using another field that the default one (Name) or multiple field.


//add filter on the members query
add_action( 'bp_pre_user_query', filter_query_members_alphabetical');

function filter_query_members_alphabetical($query){
global $bp;

//check this is an alphabetical search
if($query->query_vars['type']!='alphabetical') return $query;

//get fields ids used to sort the members
$fields_ids=array(...); // array of ids, eg. array(1,2,3,4);

if(!$fields_ids) return $query;

if(count($fields_ids)==1){//ORDER USING UNIQUE FIELD

if ($fields_ids[0]==1) return $query;//default field - acts like core, escape filter

$clauses['select'] = "SELECT DISTINCT u.user_id as id FROM {$bp->profile->table_name_data} u";
$clauses['where'][] = "u.field_id = {$fields_ids[0]}";
$clauses['where'][] = "u.value IS NOT NULL";
$clauses['orderby'] = "ORDER BY u.value";


$select[]="SELECT u.user_id as id";

//emulate fields
foreach((array)$fields_ids as $field_id){
$dummy_name = 'dummy_field_'.$field_id;
$select_max[]="MAX(CASE WHEN field_id = {$field_id} THEN value ELSE null END) AS {$dummy_name}";
//check the field is not empty
$having[]="{$dummy_name} IS NOT NULL";

if($select_max)$select[]=', '.implode(', ',$select_max);
$select[]="FROM {$bp->profile->table_name_data} u";
$select[]="GROUP BY u.user_id";

if($having)$select[]="HAVING ".implode(" AND ",$having);

$clauses['select']=implode(" ",$select);

if($orderby)$clauses['orderby'] ="ORDER BY ".implode(',',$orderby);


$clauses['where'] = ! empty( $clauses['where'] ) ? 'WHERE ' . implode( ' AND ', $clauses['where'] ) : '';

$query->uid_clauses = wp_parse_args($clauses,$query->uid_clauses);

return $query;