I'm not sure you should bully MySQL into doing exactly what you want there. I'd suggest using the following:
SELECT DISTINCT CONCAT(first, ' ', last) AS receiver_name
FROM names;
Then loop through this resultset in PHP and handle the case of ' and ' there.
If performance is a concern (you'll be doing this query often). You would benefit from not using DISTINCT on the calculated value of CONCAT(first, ' ', last) as that would require the use of a temporary table.
To tweak it, add the following index:
ALTER TABLE names ADD INDEX (last, first);
And change your query as follows:
SELECT CONCAT(first, ' ', last) AS receiver_name
FROM names
GROUP BY last, first;
You'll be able to get your values directly from the index without resorting to a temporary table or filesort.
As far as the loop goes, something like the following would work:
<?php
$mysqli = new mysqli(/* connection info */);
$sql = "SELECT CONCAT(first, ' ', last) AS receiver_name "
. 'FROM names '
. 'GROUP BY last, first';
if ($result = $mysqli->query($sql)) {
$string = '';
$count = $result->num_rows;
$rows = $result->fetch_all();
for ($i = 0; $i < $count-1; $i++) {
$string .= $rows[$i][0] . ', ';
}
$string .= ' and ' . $rows[$i][0];
echo $string; // John Smith, Bob Dole, and George Bush
}
Note This code assumes you would always have at least 2 rows returned. I'm sure you can figure out how to handle the case of only a single name returned. :)