С той базой нормально сделать иерархию для всего мира нереально, я убил на это массу времени. В результате вышло более менее нормально для США, а так как нужен был весь мир то ориентировался в иерархии по полю feature_code (список возможных вариантов geonames предоставляет). Вышло, но не совсем то что ожидалось
1. Выбор стран понятен
2. Выбор регионов с помощью hierarchy $country_geoname_id
SELECT * FROM geonames AS g INNER JOIN hierarchy AS gh ON h.childid = g.geonameid AND h.parentid ='".$country_geoname_id."'
3. Выбор городов — смотрим на города и населенные пункты, ориентируемся по штату
3.1 выбираем регион в $state
3.2 SELECT * FROM geonames WHERE country_code='".$state['country_code']."' AND admin1_code='".$state['admin1_code']."' AND feature_code IN ('ADM1', 'ADM2', 'ADM3', 'ADMD', 'PPLA', 'PPLC', 'PPL')
4. Выбор ориентиров и районов города ( для США нормально работает, в остальном мире где сомнительно)
4.1 выбираем город в $city
SELECT * FROM geonames WHERE country_code='".$city['country_code']."' AND admin1_code='".$city['admin1_code']."' AND admin2_code='".$city['admin2_code']."' AND feature_code NOT IN ('ADM1', 'ADM2', 'ADM3') AND feature_code IN ('ADM4', 'ADM5', 'PPLA', 'PPLC', 'PPL')