Если, как ты написал, через $_GET-параметр, то тебе надо выбрать только те элементы, которые переданные этим GET. Т.е. если гета нет, то делаем
WHERE id_parent = 0
И выбираем только корневые.
Если же гет есть, то делаем
WHERE id_parent = $_GET['id_parent']
И теперь выберем только вложенные в этого родителя элементы.
Ну а чтобы узнать, есть дочерние элементы или нет, можно переписать запрос:
$res = $mysqli->query("
SELECT f.*, COUNT(s.id) as children
FROM `groups` f
LEFT JOIN`groups` s
ON s.id_parent=f.id
WHERE f.id_parent = '".$_GET['id_parent']."'");
Если не ошибаюсь, то так, но надо проверить. Тогда в $row['children'] ты получишь количество прямых потомков
_______________
Второй вариант - это структурировать по id_parent, т.е. заменить $tree[$id] на $tree[$node['id_parent']][$id] . Тогда можно будет при выводе на экран перебирать не
foreach ($data_tree as $item)
а
foreach ($data_tree[$_GET['id_parent']] as $item)
_______________________
Опять таки ничто не мешает сделать банальную проверку, например:
foreach ($data_tree as $item) {
if ($item['id_parent'] == $_GET['id_parent']) {