Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Поиск в глубину SQL, Нужно составить рекурсивную процедуру 
:(
    Опции темы
AIs
Дата 16.11.2010, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 27.10.2008

Репутация: нет
Всего: нет



 Есть таблица, содержащая дерево меню:

   create table menu( id     int primary key,  -- ID пункта меню
                      parent int null,         -- ID "родителя" (null для пунктов верхнего уровня)
                      name   char(30) )        -- Наименование пункта меню

   Разработать сохраненную процедуру, позволяющую получить информацию о данном меню
   в следующем виде:

   Level    ID     Name
   ------   ----   ------------------------------------
   0        1      Меню 1
   1        5      Меню 1.1
   1        6      Меню 1.2
   2        10     Меню 1.2.1
   0        2      Меню 2
   0        3      Меню 3
   1        8      Меню 3.1
   2        12     Меню 3.1.1
   2        13     Меню 3.1.2
   1        9      Меню 3.2
   ...

   Т.е., пункты меню должны быть отсортированы так, чтобы при их обработке клиентское 
   приложение могло построить меню за "один проход". Каждая следующая запись должна быть 
   либо подпунктом предыдущей (если ее уровень вложенности больше, чем у предыдущей),
   либо иметь общего родителя с предыдущей записью того же уровня вложенности.

Фактически, это поиск в глубину. Но для этого нужно либо как-то делать UNION выборок, получаемых на каждом уровне, либо каким-то образом вытаскивать не все пункты с одного уровня, а по одному. Пока есть такое:
SELECT '0' AS 'level', id, name FROM menu
WHERE parent IN (NULL)

UNION

SELECT '1' AS 'level', id, name FROM menu
WHERE parent IN
(SELECT id FROM menu
WHERE parent IN (NULL))

UNION

SELECT '2' AS 'level', id, name FROM menu
WHERE parent IN
(SELECT id FROM menu
WHERE parent IN
(SELECT id FROM menu
WHERE parent IN (NULL)))

Естественно, это не то, потому что алгоритм не рекурсивный, а линейный, но результат он выдает в правильном порядке. Нужно либо превратить этот алгоритм в рекурсивную процедуру, либо придумать что-то еще.
PM MAIL   Вверх
Zloxa
Дата 16.11.2010, 10:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Рекурсивные запросы платформозависимы.
Укажите платформу

Добавлено через 2 минуты и 10 секунд
union выполняет дополнительную сортировку для того, чтобы обеспечить уникальность возвращаемого набора.
Потому использовать его нужно только тогда, когда это действительно нужно.
В вашем случае, следовало бы испльзовать union all.


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
AIs
Дата 16.11.2010, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 27.10.2008

Репутация: нет
Всего: нет



Прошу прощения, забыл указать.
Adaptive Server Enterprise/12.5.3/EBF 12876 ESD#4/P/Linux Intel/Enterprise Linux/ase1253/1923/32-bit/OPT/Thu Sep  8 06:16:18 2005
PM MAIL   Вверх
Zloxa
Дата 16.11.2010, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



rtfm Selecting hierarchical data

Это сообщение отредактировал(а) Zloxa - 16.11.2010, 10:46


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
AIs
Дата 16.11.2010, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 27.10.2008

Репутация: нет
Всего: нет



Дело в том, что я пытался использовать такое решение:
WITH RECURSIVE
 Rec (id, parent, name)
 AS (
   SELECT id, parent, name FROM menu
   UNION ALL
   SELECT Rec.id, Rec.parent, Rec.name
    FROM Rec, menu
    WHERE Rec.id = menu.parent
   )

Но получил ошибку:
Error: Incorrect syntax near the keyword 'WITH'.

SQLState:  ZZZZZ
ErrorCode: 156
PM MAIL   Вверх
Zloxa
Дата 16.11.2010, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



а вы "select * from Rec" в конце упустили при публикации на форум или в запросе тоже забыли его добавить?

Добавлено через 3 минуты и 49 секунд
И еще, наверное следовало было бы сразу упомянуть.
Я не являюсь специалистом по sybase и не знаю имеет ли отношение sql anywhere, ссылку на документацию к которому я дал к ASE.
Т.к. в документации по ASE содержит только релизбюлетени, я предположил что sql anywhere это языковое расширение ASE, что далеко может быть не факт.



--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
AIs
Дата 16.11.2010, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 27.10.2008

Репутация: нет
Всего: нет



Только при публикации, но это ничего не меняет.
Запрос:
WITH RECURSIVE
 Rec (id, parent, name)
 AS (
   SELECT id, parent, name FROM menu
   UNION ALL
   SELECT Rec.id, Rec.parent, Rec.name
    FROM Rec, menu
    WHERE Rec.id = menu.parent
   )
   SELECT * FROM Rec
   WHERE parent is null

Результат:
Error: Incorrect syntax near the keyword 'WITH'.

SQLState:  ZZZZZ
ErrorCode: 156

Видимо, не все версии Sybase поддерживают это ключевое слово.
"На текущей момент ASA имеет поддержку наиболее современных расширений SQL (Common Table Expression, Recursive query, OLAP window function и т.д.)."

FAQ / Sybase
PM MAIL   Вверх
Zloxa
Дата 16.11.2010, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(AIs @  16.11.2010,  11:29 Найти цитируемый пост)
На текущей момент ASA

у вас ASE

Добавлено через 11 минут и 7 секунд
Да, судя по всему, SQL Anywhere никакого отношения к ASE не имеет, и ASE не поддерживает СТЕ и , соответствено, рекурсивные запросы.


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
AIs
Дата 16.11.2010, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 27.10.2008

Репутация: нет
Всего: нет



Все-таки, как же можно решить эту задачу без CTE?
PM MAIL   Вверх
Zloxa
Дата 16.11.2010, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Когдато давно-давно, для MS SQL 2000 я решал задачу рекурсивного обхода процедурой на TSQL, используя особенность как их бишь там, кажись "динамических" курсоров. В процессе обхода курсора я добавлял в его хвост данные, которые обходил, получается, тем же циклом. Если бы у вас получилось  реализовать средствами TSQL сайбейза, мне было бы интересно взглянуть на решение. Однако такое решение мало чем отличается от решения выборки иерархии с клиента.

Это сообщение отредактировал(а) Zloxa - 16.11.2010, 13:19


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0698 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.