![]() |
Модераторы: skyboy |
![]() ![]() ![]() |
|
AIs |
|
|||
Новичок Профиль Группа: Участник Сообщений: 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))) Естественно, это не то, потому что алгоритм не рекурсивный, а линейный, но результат он выдает в правильном порядке. Нужно либо превратить этот алгоритм в рекурсивную процедуру, либо придумать что-то еще. |
|||
|
||||
Zloxa |
|
|||
![]() Чо? ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3473 Регистрация: 12.9.2008 Репутация: 53 Всего: 161 |
Рекурсивные запросы платформозависимы.
Укажите платформу Добавлено через 2 минуты и 10 секунд union выполняет дополнительную сортировку для того, чтобы обеспечить уникальность возвращаемого набора. Потому использовать его нужно только тогда, когда это действительно нужно. В вашем случае, следовало бы испльзовать union all. -------------------- Достоверно известно, что 89% людей доверяют статистике взятой с потолка ![]() |
|||
|
||||
AIs |
|
|||
Новичок Профиль Группа: Участник Сообщений: 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 |
|||
|
||||
Zloxa |
|
|||
![]() Чо? ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3473 Регистрация: 12.9.2008 Репутация: 53 Всего: 161 |
-------------------- Достоверно известно, что 89% людей доверяют статистике взятой с потолка ![]() |
|||
|
||||
AIs |
|
|||
Новичок Профиль Группа: Участник Сообщений: 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 |
|||
|
||||
Zloxa |
|
|||
![]() Чо? ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3473 Регистрация: 12.9.2008 Репутация: 53 Всего: 161 |
а вы "select * from Rec" в конце упустили при публикации на форум или в запросе тоже забыли его добавить?
Добавлено через 3 минуты и 49 секунд И еще, наверное следовало было бы сразу упомянуть. Я не являюсь специалистом по sybase и не знаю имеет ли отношение sql anywhere, ссылку на документацию к которому я дал к ASE. Т.к. в документации по ASE содержит только релизбюлетени, я предположил что sql anywhere это языковое расширение ASE, что далеко может быть не факт. -------------------- Достоверно известно, что 89% людей доверяют статистике взятой с потолка ![]() |
|||
|
||||
AIs |
|
|||
Новичок Профиль Группа: Участник Сообщений: 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 |
|||
|
||||
Zloxa |
|
|||
![]() Чо? ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3473 Регистрация: 12.9.2008 Репутация: 53 Всего: 161 |
у вас ASE Добавлено через 11 минут и 7 секунд Да, судя по всему, SQL Anywhere никакого отношения к ASE не имеет, и ASE не поддерживает СТЕ и , соответствено, рекурсивные запросы. -------------------- Достоверно известно, что 89% людей доверяют статистике взятой с потолка ![]() |
|||
|
||||
AIs |
|
|||
Новичок Профиль Группа: Участник Сообщений: 14 Регистрация: 27.10.2008 Репутация: нет Всего: нет |
Все-таки, как же можно решить эту задачу без CTE?
|
|||
|
||||
Zloxa |
|
|||
![]() Чо? ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3473 Регистрация: 12.9.2008 Репутация: 53 Всего: 161 |
Когдато давно-давно, для MS SQL 2000 я решал задачу рекурсивного обхода процедурой на TSQL, используя особенность как их бишь там, кажись "динамических" курсоров. В процессе обхода курсора я добавлял в его хвост данные, которые обходил, получается, тем же циклом. Если бы у вас получилось реализовать средствами TSQL сайбейза, мне было бы интересно взглянуть на решение. Однако такое решение мало чем отличается от решения выборки иерархии с клиента.
Это сообщение отредактировал(а) Zloxa - 16.11.2010, 13:19 -------------------- Достоверно известно, что 89% людей доверяют статистике взятой с потолка ![]() |
|||
|
||||
![]() ![]() ![]() |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Составление SQL-запросов | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |