То, что вы хотите получить можно сделать таким запросом:
select S.*,
(select S1.location from services S1 where S1.main = S.main and (S1.list is null or S1.list = '')) head_index
from services S
order by head_index, S.list is null or S.list = '' desc, S.location is null or S.location = '' desc, S.location
А потом вывести таким скриптом:
$sql = "select S.*,
(select S1.location from services S1 where S1.main = S.main and (S1.list is null or S1.list = '')) head_index
from services S
order by head_index, S.list is null or S.list = '' desc, S.location is null or S.location = '' desc, S.location";
$res = mysqli_query($conn, $sql);
$cat_index = 0;
while($row = msqli_fetch_assoc($res))
{
if(is_null($row['list']))
{
if($cat_index > 0)
echo '</ul>'; // закрытие списка
echo '<p>'.$row['main'].'</p><ul>'; // название категории, начало списка
$cat_index++; // считаем категорию, чтобы правильно закрывать списковые теги
}
else
{
echo '<li>'.$row['list'].'</li>';
}
}
if($cat_index > 0)
echo '</ul>'; // закрытие списка
А вообще, многоуровневые списки делаются по-другому.