diff --git bp-groups/bp-groups-classes.php bp-groups/bp-groups-classes.php
index c540a49..ddad9b2 100644
--- bp-groups/bp-groups-classes.php
+++ bp-groups/bp-groups-classes.php
@@ -1436,10 +1436,10 @@ class BP_Group_Member_Query extends BP_User_Query {
 	 */
 	public function setup_hooks() {
 		// Take this early opportunity to set the default 'type' param
-		// to 'last_modified', which will ensure that BP_User_Query
+		// to 'last_joined', which will ensure that BP_User_Query
 		// trusts our order and does not try to apply its own
 		if ( empty( $this->query_vars_raw['type'] ) ) {
-			$this->query_vars_raw['type'] = 'last_modified';
+			$this->query_vars_raw['type'] = 'last_joined';
 		}
 
 		// Set the sort order
@@ -1471,6 +1471,7 @@ class BP_Group_Member_Query extends BP_User_Query {
 			'group_id'     => 0,
 			'group_role'   => array( 'member' ),
 			'is_confirmed' => true,
+			'type'         => 'last_joined',
 		) );
 
 		$group_member_ids = $this->get_group_member_ids();
@@ -1508,7 +1509,6 @@ class BP_Group_Member_Query extends BP_User_Query {
 			'where'   => array(),
 			'orderby' => '',
 			'order'   => '',
-			'limit'   => '',
 		);
 
 		/** WHERE clauses *****************************************************/
@@ -1571,16 +1571,20 @@ class BP_Group_Member_Query extends BP_User_Query {
 
 		$sql['where'] = ! empty( $sql['where'] ) ? 'WHERE ' . implode( ' AND ', $sql['where'] ) : '';
 
-		/** ORDER BY clause ***************************************************/
-
-		// @todo For now, mimicking legacy behavior of
-		// bp_group_has_members(), which has us order by date_modified
-		// only. Should abstract it in the future
+		// We fetch group members in order of last_joined, regardless
+		// of 'type'. If the 'type' value is not 'last_joined' or
+		// 'first_joined', the order will be overridden in
+		// BP_Group_Member_Query::set_orderby()
 		$sql['orderby'] = "ORDER BY date_modified";
-		$sql['order']   = "DESC";
+		$sql['order']   = 'first_joined' === $this->query_vars['type'] ? 'ASC' : 'DESC';
+
+		$this->group_member_ids = $wpdb->get_col( "{$sql['select']} {$sql['where']} {$sql['orderby']} {$sql['order']}" );
 
-		/** LIMIT clause ******************************************************/
-		$this->group_member_ids = $wpdb->get_col( "{$sql['select']} {$sql['where']} {$sql['orderby']} {$sql['order']} {$sql['limit']}" );
+		/**
+		 * Use this filter to build a custom query (such as when you've
+		 * defined a custom 'type').
+		 */
+		$this->group_member_ids = apply_filters( 'bp_group_member_query_group_member_ids', $this->group_member_ids, $this );
 
 		return $this->group_member_ids;
 	}
@@ -1588,22 +1592,31 @@ class BP_Group_Member_Query extends BP_User_Query {
 	/**
 	 * Tell BP_User_Query to order by the order of our query results.
 	 *
-	 * This implementation assumes the 'last_modified' sort order
-	 * hardcoded in BP_Group_Member_Query::get_group_member_ids().
+	 * We only override BP_User_Query's native ordering in case of the
+	 * 'last_joined' and 'first_joined' $type parameters.
 	 *
 	 * @param BP_User_Query $query BP_User_Query object.
 	 */
 	public function set_orderby( $query ) {
+
 		$gm_ids = $this->get_group_member_ids();
+
 		if ( empty( $gm_ids ) ) {
 			$gm_ids = array( 0 );
 		}
 
-		// The first param in the FIELD() clause is the sort column id
-		$gm_ids = array_merge( array( 'u.id' ), wp_parse_id_list( $gm_ids ) );
-		$gm_ids_sql = implode( ',', $gm_ids );
+		// For 'last_joined' and 'first_joined' types, we force
+		// the order according to the query performed in
+		// BP_Group_Member_Query::get_group_members(). Otherwise, fall
+		// through and let BP_User_Query do its own ordering.
+		if ( in_array( $query->query_vars['type'], array( 'last_joined', 'first_joined' ) ) ) {
+
+			// The first param in the FIELD() clause is the sort column id
+			$gm_ids = array_merge( array( 'u.id' ), wp_parse_id_list( $gm_ids ) );
+			$gm_ids_sql = implode( ',', $gm_ids );
 
-		$query->uid_clauses['orderby'] = "ORDER BY FIELD(" . $gm_ids_sql . ")";
+			$query->uid_clauses['orderby'] = "ORDER BY FIELD(" . $gm_ids_sql . ")";
+		}
 
 		// Prevent this filter from running on future BP_User_Query
 		// instances on the same page
diff --git bp-groups/bp-groups-functions.php bp-groups/bp-groups-functions.php
index a27a499..d63f980 100644
--- bp-groups/bp-groups-functions.php
+++ bp-groups/bp-groups-functions.php
@@ -422,6 +422,7 @@ function groups_get_group_members( $args = array() ) {
 		'exclude'             => false,
 		'group_role'          => array(),
 		'search_terms'        => false,
+		'type'                => 'last_joined',
 	) );
 
 	// For legacy users. Use of BP_Groups_Member::get_all_for_group()
@@ -455,7 +456,7 @@ function groups_get_group_members( $args = array() ) {
 			'group_role'     => $r['group_role'],
 			'exclude'        => $r['exclude'],
 			'search_terms'   => $r['search_terms'],
-			'type'           => 'last_modified',
+			'type'           => $r['type'],
 		) );
 
 		// Structure the return value as expected by the template functions
diff --git bp-groups/bp-groups-template.php bp-groups/bp-groups-template.php
index 675409e..6850194 100644
--- bp-groups/bp-groups-template.php
+++ bp-groups/bp-groups-template.php
@@ -1982,6 +1982,7 @@ class BP_Groups_Group_Members_Template {
 			'exclude_banned'      => 1,
 			'group_role'          => false,
 			'search_terms'        => false,
+			'type'                => 'last_joined',
 		) );
 
 		// @todo No
@@ -2085,6 +2086,9 @@ class BP_Groups_Group_Members_Template {
  *     @type bool|int True (or 1) to exclude banned users from results.
  *           Default: 1.
  *     @type array $group_role Optional. Array of group roles to include.
+ *     @type string $type Optional. Sort order of results. 'last_joined',
+ *           'first_joined', or any of the $type params available in
+ *           {@link BP_User_Query}. Default: 'last_joined'.
  *     @type string $search_terms Optional. Search terms to match.
  * }
  */
@@ -2101,6 +2105,7 @@ function bp_group_has_members( $args = '' ) {
 		'exclude_banned'      => 1,
 		'group_role'          => false,
 		'search_terms'        => false,
+		'type'                => 'last_joined',
 	) );
 
 	if ( empty( $r['search_terms'] ) && ! empty( $_REQUEST['s'] ) )
diff --git tests/testcases/groups/class-bp-group-member-query.php tests/testcases/groups/class-bp-group-member-query.php
index 46e44f9..b38943f 100644
--- tests/testcases/groups/class-bp-group-member-query.php
+++ tests/testcases/groups/class-bp-group-member-query.php
@@ -334,4 +334,92 @@ class BP_Tests_BP_Group_Member_Query_TestCases extends BP_UnitTestCase {
 		$this->assertEquals( array( $u2 ), $ids );
 	}
 
+	/**
+	 * @group type
+	 */
+	public function test_get_with_type_last_joined() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 500 ),
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'type' => 'last_joined',
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u2, $u1 ), $ids );
+	}
+
+	/**
+	 * @group type
+	 */
+	public function test_get_with_type_first_joined() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user();
+		$u2 = $this->create_user();
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 500 ),
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'type' => 'first_joined',
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u1, $u2 ), $ids );
+	}
+
+	/**
+	 * @group type
+	 */
+	public function test_get_with_type_alphabetical() {
+		$g = $this->factory->group->create();
+		$u1 = $this->create_user( array(
+			'display_name' => 'AAA',
+		) );
+		$u2 = $this->create_user( array(
+			'display_name' => 'CCC',
+		) );
+		$u3 = $this->create_user( array(
+			'display_name' => 'BBB',
+		) );
+		$time = time();
+
+		$this->add_user_to_group( $u1, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 100 ),
+		) );
+
+		$this->add_user_to_group( $u2, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 200 ),
+		) );
+
+		$this->add_user_to_group( $u3, $g, array(
+			'date_modified' => gmdate( 'Y-m-d H:i:s', $time - 300 ),
+		) );
+
+		$query_members = new BP_Group_Member_Query( array(
+			'group_id' => $g,
+			'type' => 'alphabetical',
+		) );
+
+		$ids = wp_parse_id_list( array_keys( $query_members->results ) );
+		$this->assertEquals( array( $u1, $u3, $u2 ), $ids );
+	}
 }
