Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, naf_2000, Вы писали:
_>>то берем ее, иначе вычисляем для родителя GetVal(aT.Parent) и т.д.. Если нет в иерархии, то NULL. _>>Требуется оптимальное по скорости решение
___>Как часто мне приходится задавать этот вопрос... ___>СУБД и ее версия?
Похоже на Oracle. Поэтому будем считать что это Oracle.
Можно все сделать одним запросом:
select T.*, R.*
from T
left join R
on T.ID = R.TID
where R.ID is not null
start with T.ID = :starting_t_id
connect by prior T.Parent = T.ID and prior R.ID is null
Для скорости возможно стоит подумать над тем, чтобы слить эти две таблицы в одну, избежав тем самым постоянного выполнения джойна этих двух таблиц при каждом выполнении запроса.
Здравствуйте, Мурлакотам, Вы писали:
М>Здравствуйте, naf_2000, Вы писали:
_>>Поиск в иерархии _>>Требуется оптимальное по скорости решение
М>AFAIK, длительность поиска по иерархии — факт, на который повлиять средствами реляционных СУБД невозможно. Сам в таких случая применял два подхода: М>1. Велосипедный. Вся иерархия считывается в собственную структуру данных и далее поиск производится уже в ней (либо рекурсивно, либо по развёрнутому плоскому представлению, построенному предварительно с применением рекурсии).
Так себе решение.
М>2. Использование иерархических СУБД. Иерархическая часть БД выносится на альтернативный движок (например, в LDAP), который и решает задачу поиска по иерархии.
Чушь.
Задача легко решается рекурсивным запросом и в обычных реляционных СУБД.
Здравствуйте, naf_2000, Вы писали:
_>то берем ее, иначе вычисляем для родителя GetVal(aT.Parent) и т.д.. Если нет в иерархии, то NULL. _>Требуется оптимальное по скорости решение
Как часто мне приходится задавать этот вопрос...
СУБД и ее версия?
create table T(
ID integer not null primary key,
Name varchar(100),
Parent integer --ссылка на запись этой же таблицы, для верхнего уровня NULL (без зацикливаний)
)
create table R(
ID integer not null primary key,
TID integer not null unique, --ссылка на элемент таблицы T
Val integer
)
требуется написать хранимую процедуру GetVal(aT integer), получающую на входе ключ таблицы T, на выходе значение Val, определеяемое по правилу:
если есть запись в
select Val from R where TID=:aT
то берем ее, иначе вычисляем для родителя GetVal(aT.Parent) и т.д.. Если нет в иерархии, то NULL.
Требуется оптимальное по скорости решение
Здравствуйте, naf_2000, Вы писали:
_>Поиск в иерархии _>Требуется оптимальное по скорости решение
AFAIK, длительность поиска по иерархии — факт, на который повлиять средствами реляционных СУБД невозможно. Сам в таких случая применял два подхода:
1. Велосипедный. Вся иерархия считывается в собственную структуру данных и далее поиск производится уже в ней (либо рекурсивно, либо по развёрнутому плоскому представлению, построенному предварительно с применением рекурсии).
2. Использование иерархических СУБД. Иерархическая часть БД выносится на альтернативный движок (например, в LDAP), который и решает задачу поиска по иерархии.
_>требуется написать хранимую процедуру GetVal(aT integer), получающую на входе ключ таблицы T, на выходе значение Val, определеяемое по правилу: _>если есть запись в _>
_>select Val from R where TID=:aT_>
_>то берем ее, иначе вычисляем для родителя GetVal(aT.Parent) и т.д.. Если нет в иерархии, то NULL. _>Требуется оптимальное по скорости решение
Оптимально будет делать цикл (на T-SQL) с запросами значения R.Val для основного значения T.ID, для иерархии его родителей, пока не будет обнаружено заданное значение R.Val или не кончится иерархия.
Сходили на собеседование в Связной?
Только там требовалось решение для 5-уровневой иерархии на языке 1С8 (запросы + модуль).
Например, такой цикл в 7 раз быстрее одного запроса с 5-ю объединениями (при индексации всех FK, конечно).
Никогда не бойся браться делать то, что делать не умеешь. Помни, ковчег был построен любителем. Профессионалы построили Титаник...
Здравствуйте, VVP, Вы писали:
VVP>Оптимально будет делать цикл (на T-SQL) с запросами значения R.Val для основного значения T.ID, для иерархии его родителей, пока не будет обнаружено заданное значение R.Val или не кончится иерархия.
Еще один "велосипедист"? Оптимально будет сделать рекурсивный запрос через Common Table Expression.
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, VVP, Вы писали:
VVP>>Оптимально будет делать цикл (на T-SQL) с запросами значения R.Val для основного значения T.ID, для иерархии его родителей, пока не будет обнаружено заданное значение R.Val или не кончится иерархия.
___>Еще один "велосипедист"? Оптимально будет сделать рекурсивный запрос через Common Table Expression.
VVP>Только там требовалось решение для 5-уровневой иерархии на языке 1С8 (запросы + модуль). VVP>Например, такой цикл в 7 раз быстрее одного запроса с 5-ю объединениями (при индексации всех FK, конечно).
Чего-то имею я сомнения. Можешь примерно привести характеристики этой иерархии (сколько всего элементов, сколько корневых, второго уровня и т.д.), не поленюсь проверить у себя.
Здравствуйте, G0ga, Вы писали:
G>Здравствуйте, _d_m_, Вы писали:
___>>Здравствуйте, naf_2000, Вы писали:
_>>>то берем ее, иначе вычисляем для родителя GetVal(aT.Parent) и т.д.. Если нет в иерархии, то NULL. _>>>Требуется оптимальное по скорости решение
___>>Как часто мне приходится задавать этот вопрос... ___>>СУБД и ее версия?
G>Могу порекомендовать http://rsdn.ru/article/alg/dbtree.xml