Получить полный адрес из одной таблицы

Kozerog
Дата: 03.11.2008 21:25:27
Таблица адресов имеет следующую структуру

ID, Namе, Parent_id

1, Россия, 0
2, Московская обл, 1
3. Мытищинский район, 2
4, Тайнинка, 3

И так для всей Руси Великой

Нужно быстро вынимать по ID населенного пункта весь адрес.

Проблема усугубляется тем, что структура адресов не одинаковая, у некоторых населенных пунктов
нет районов, иногда присутствую края и т.п.

Подскажите вариант наиболее быстрой выборки нужных данных . Таблица большая. Запросы идут часто.

Спасибо.
wasisdas
Дата: 03.11.2008 22:20:25
и чем же иерархический запрос не подходит (CONNECT BY ...)?
Добрый Э - Эх
Дата: 05.11.2008 05:12:38
Как вариант:
with address as (
select 1 as id, 'Россия' as name, 0 as parent_id from dual union all
select 2 as id, 'Московская обл' as name, 1 as parent_id from dual union all
select 3 as id, 'Мытищинский район' as name, 2 as parent_id from dual union all
select 4 as id, 'Тайнинка' as name, 3 as parent_id from dual
)
--
--
--
select replace(rtrim(max(reverse(sys_connect_by_path(reverse(name),',')))
          keep(dense_rank last oprder by level),','),',',', ') as full_address_str
  from address
 start with id = 4
 connect by prior parent_id = id

Два НО:
1) reverse до версии 11g - недокументированная функция
2) фокус с reverse "корректно" сработает лишь на однобайтовых кодировках, в противном же случае выдаст невнятный фарш...
Добрый Э - Эх
Дата: 05.11.2008 05:18:28
Более корректным будет строить дерево два раза: первый раз в обратном порядке от населенного пункта до страны, чтобы выбрать интересующую нас ветвь, второй раз - в прямом порядке от страны до населенного пункта, чтобы выстроить полную строку адреса:
with address as (
select 1 as id, 'Россия' as name, 0 as parent_id from dual union all
select 2 as id, 'Московская обл' as name, 1 as parent_id from dual union all
select 3 as id, 'Мытищинский район' as name, 2 as parent_id from dual union all
select 4 as id, 'Тайнинка' as name, 3 as parent_id from dual
)
--
--
--
select replace(ltrim(max(sys_connect_by_path(name,','))
          keep(dense_rank last oprder by level),','),',',', ') as full_address_str
  from (
         select id, name, parent_id, 
                row_number() over(order by lv desc) as rn
           from (
                  select id, name, parent_id, level as lv
                    from address
                   start with id = 4
                   connect by prior parent_id = id
                )
       )
 start with rn = 1
 connect by prior id = parent_id
orawish
Дата: 05.11.2008 08:03:46
Добрый Э - Эх
Более корректным будет строить дерево два раза: первый раз в обратном порядке ..

Иерархический запрос, обратный SYS_CONNECT_BY_PATH
orawish
Дата: 05.11.2008 08:21:17
orawish
Добрый Э - Эх
Более корректным будет строить дерево два раза: первый раз в обратном порядке ..

Иерархический запрос, обратный SYS_CONNECT_BY_PATH

мм.. ссылка не очень оказалась..
На самом деле - я невнятный фарш хотел обсудить. С этим вполне можно бороться при любой уникодице..
VBR
Дата: 05.11.2008 09:39:51
В Oracle недавно.
Какие минусы такого варианта?

with address as (
select 1 as id, 'Россия' as name, 0 as parent_id from dual union all
select 2 as id, 'Московская обл' as name, 1 as parent_id from dual union all
select 3 as id, 'Мытищинский район' as name, 2 as parent_id from dual union all
select 4 as id, 'Тайнинка' as name, 3 as parent_id from dual
)
         select wm_concat(name)
           from (
           
                  select name, level as lv
                    from address
                   start with id = 4
                   connect by prior parent_id = id
                   order by 2 desc
                )
xa xa
Дата: 05.11.2008 10:53:39
wm_concat(name)
А это что такое?
Добрый Э - Эх
Дата: 05.11.2008 11:04:32
xa xa
wm_concat(name)
А это что такое?
Недокументированная в версии 10g штука, представляющая собой агрегатную функцию конкатенации. :)
Elic
Дата: 05.11.2008 11:04:41
xa xa
wm_concat(name)
А это что такое?
Это 10g. STFF