-
Приветствую Вас Мастера.
Есть простая таблица и для простоты пример: у таблицы два поля id и id_roditel в id храниться уникальное значение, а в id_roditel храниться ссылка на поле id. Как вы уже поняли это связный иерархический список. Хочу выбрать всю ветку потомков, указав какой то конкретный узел. Наведите на мысль как составить такой sql запрос.
-
Стандартный алгоритм рекурсии - в инете масса примеров
-
> MsGuns © (19.06.08 23:06) [1]
>
> Стандартный алгоритм рекурсии - в инете масса примеров
В настоящее время я решаю проблему при помощи хранимой функции- т.е. по сути программно, но заинтересовало как это сделать посредством только sql запроса.
-
Если тебя смущает наличие UDF, никто не мешает весь её текст поместить в SQL компонента.
Получить нужное одним SELECT, ИМХО, невозможно.
-
WITH TempTbl AS (SELECT npp, roditel, 1 AS lv
FROM Potrebitel AS A
WHERE (npp = 6)
UNION ALL
SELECT node.npp, node.roditel, ft.lv + 1 AS lv
FROM Potrebitel AS node INNER JOIN
TempTbl AS ft ON node.roditel = ft.npp AND node.roditel <> node.npp)
SELECT npp, roditel, lv
FROM TempTbl AS pp
в npp=6 помещаешь номер узла и в результате запроса получаешь всех потомков. Очень удобная штука.
Почитай тут
http://www.sqlbooks.ru/readarticle.aspx?part=02&file=sql200509
-
Не существует решения в рамках стандартных конструкций SQL. И быть не может, ибо "иерархические списки" (т.е. дерево) никакого отношения к реляционной модели не имеют.
Но в некоторых диалектах SQL существуют специально введенные искусственные конструкции, специально для этого предназначенные.
-
Да, мой пример справедлив для MS SQL 2005.
хотя в приведённой ссылке упоминается Стандарт ISO SQL:1999 - предусматривающий рекрусивные запросы - может с их помощю можно попробывать.
-
SuperChel (19.06.08 22:19)
Можно без рекурсии, в функции временная таблица + цикл, могу для примера опубликовать свою функцию. Кстати работает быстрее чем WITH на 2005. Но все равно лучше написать триггера, которые будут наполнять/изменять таблицу содержащую нужный набор записей.
-
Кстати вариант с триггером ИМХО очень перспективный вариант.
-
> Кстати вариант с триггером ИМХО очень перспективный вариант.
От ситуации зависит. Может быть и перспективным. А может - и нет.
-
чё-то я не понял: причем тут триггера?
-
>SuperChel (20.06.08 00:32) [2]
>как это сделать посредством только sql запроса.
Никак. Делается две хранимки - одна "складывает" полученных "деток" (входимость в парент непосредственная) в результсет, вторая - выборка "деток", которая вызывается рекурсивно.
>stas © (20.06.08 09:35) [7]
>Можно без рекурсии, в функции временная таблица + цикл, могу для примера >опубликовать свою функцию. Кстати работает быстрее чем WITH на 2005. Но все >равно лучше написать триггера, которые будут наполнять/изменять таблицу >содержащую нужный набор записей.
1. Через временную таблицу не быстрее
2. Зачем там with ?
3. Каким боком там вообще триггеры ?
-
MsGuns © (20.06.08 10:42) [11]
1. быстрее чем with
2. with синтаксис 2005
3.Тот набор записей, который содержит иеархический список, хранится непосредственно в таблице, которая в свою очередь наполняется триггерами, таким образом при выборке используется таблица, без всяких функций и рекурсий.
-
> 3.Тот набор записей, который содержит иеархический список,
> хранится непосредственно в таблице, которая в свою очередь
> наполняется триггерами, таким образом при выборке используется
> таблица, без всяких функций и рекурсий.
>
Таблица изменяется 3 раза в секунду, а запрос на выборку данных раз в час нужен.
Тоже триггеры будешь лепить?
А многопользовательский доступ к этой временной таблице? А её содержимое при перезагрузке сервера?
В частном маленьком случае этот вариант ещё может пригодиться, в общем и целом - фтопку.
-
>stas © (20.06.08 10:52) [12]
>2. with синтаксис 2005
Чем with 2005-го отличается от with 2000-го ?
>3.Тот набор записей, который содержит иеархический список, хранится >непосредственно в таблице, которая в свою очередь наполняется триггерами, таким >образом при выборке используется таблица, без всяких функций и рекурсий.
Надо полагать, что таблица постоянная (иначе как в нее встромить триггеры) ? Тогда вопрос на засыпку - как эта таблица будет "обслуживать" несколько одновременных запросов на разузлование ?
Вы придумали велосипед с треугольными колесами и вторым рулем вместо седла. И пытаетесь его "запатентовать" ;)
-
> Таблица изменяется 3 раза в секунду, а запрос на выборку
> данных раз в час нужен.
> Тоже триггеры будешь лепить?
> А многопользовательский доступ к этой временной таблице?
> А её содержимое при перезагрузке сервера?
ну тут наверное типа временная таблица с тими триггерами (есть такое в 2005?) и при добавлении записи в нее триггер вытаскивает типа "детей", добавляет их в нее и получается в общем и целом бред, хотя работать будет
-
Ega23 © (20.06.08 10:57) [13]
что имеете ввиду под маленьким случаем?
Я предложил несколько вариантов выбираемый вариант зависит от задачи.
Зачастую все происходит наоборот, таблица корректируется не так уж и часто, а выборка используется часто.
Пример разузловка оборудования на большом предприятии, поступление нового оборудование происходит раз в день. А ремонты существующего и затраты на ремонты постоянно...
А многопользовательский доступ разрулит MSSQL.
> А её содержимое при перезагрузке сервера?
Вы запутались...
1-й вариант наполняем в нутри функции временную таблицу и возвращаем результат
2-й в постоянную ведем запись триггерами.
-
Внимательно читайте:
1. Можно без рекурсии, в функции временная таблица + цикл, могу для примера опубликовать свою функцию. Кстати работает быстрее чем WITH на 2005.
2. Но все равно лучше написать триггера, которые будут наполнять/изменять таблицу содержащую нужный набор записей.
1 и 2 не связаны между собой!!!
-
> 2-й в постоянную ведем запись триггерами
?????? и что получится в результате
через некоторое время она станет копией основного справочника, создавать еще одну "постоянную" таблицу?
-
В ИБ, где есть suspend (т.е. отсылка клиенту записи сразу после ее выборки без предварительного кэширования во врем.таблицу, которую затем в готовом виде сервер и передает клиенту,- как в мсскл), весь алгоритм можно с успехом реализовать одной-единственной хранимкой, которая вызывает саму себя рекурсивно.
Работает ясно, просто и быстро.
Пример можно подсмотреть в "Мир интербэйз" Вострикова-Ковязина (Часть I, глава ИМХО о хранимках)