я крут

простите мне мой французский, но я неебически крут.
я написал запрос (если быть точным, это несколько запросов, но в версиях начиная с 4.0 можно за счет union'а свести без проблем к одному) к mysql который работает даже на 3.23 и выдает путь в дереве до узла. при этом никаких специальных предположений про дерево не вводится. у него может быть несколько корней, сколько угодно уровней, имена узлов могут быть какими угодно (в смысле содержать любые символы, не мешающие mysql нормально работать с ними, быть различной длины, даже блин узел дерева может иметь айдишник меньший, чем у его предка).



set @ids:='', @tmp:='', @str:='', @path:='', @aim:=14;
select @aim as aim, '' as path from gal_categ as gal where (if(if((@tmp:=locate(concat_ws('','([',gal.id,']'),@ids)),@tmp,@tmp:=locate(concat_ws('','([',gal.id,'['),@ids)),(@ids:=insert(@ids,@tmp,length(@str:=substring(@ids,@tmp + 1,locate(')',@ids,@tmp) - @tmp - 1))+2,'')),(@str:=concat_ws('','[',gal.id,']')))!='') and (if(if((@tmp:=locate(concat_ws('','[',gal.id_parent,']'),@ids)),@tmp,@tmp:=locate(concat_ws('','[',gal.id_parent,'['),@ids)),((@ids:=insert(@ids,@tmp + length(gal.id_parent) + 1,0,@str))!=''),(@ids:=insert(@ids,length(@ids) + 1,0,concat_ws('','([',gal.id_parent,@str,'])')))!=''))='';
set @ids:=concat(left(@ids,if(@tmp:=locate(concat_ws('','[',@aim,']'),@ids),@tmp + length(@aim),locate(concat_ws('','[',@aim,'['),@ids) + length(@aim))),'[');
select @aim as aim, @ids as ids from gal_categ as gal where (@tmp:=locate('[', reverse(substring_index(@ids, ']', 1))))!=concat('-', gal.id) and (@ids:=insert(@ids, locate(']', @ids) - @tmp, @tmp + 1, ''))='';
select @aim as aim, @ids as ids from gal_categ as gal where (@tmp:=locate('[', reverse(substring_index(@ids, ']', 1))))!=concat('-', gal.id) and (@ids:=insert(@ids, locate(']', @ids) - @tmp, @tmp + 1, ''))='';
set @ids:=substring(@ids, locate('[', @ids, 3));
select @aim as aim, @ids as ids from gal_categ as gal where (@tmp:=locate(concat_ws('','[',gal.id,'['),@ids)) and (@ids:=insert(@ids,@tmp + length(gal.id) + 1,0,concat_ws('','(',length(gal.name),')')))!='' and (@path:=concat(@path,repeat('/',length(gal.name)+3)))='';
set @tmp:=0, @pos:=0, @str:=0;
select @aim as aim, @ids as ids from gal_categ as gal where (if(@pos:=locate('(', @ids),(@ids:=insert(@ids,@pos,length(@str:=substring(@ids,@pos+1,locate(')',@ids) - @pos - 1)) + 2,concat_ws('', '{', @tmp:=@tmp+@str+3, '}'))),('1'))='');
select @aim as aim, @str as str, @ids as ids, @path as path from gal_categ as gal where (if(@tmp:=locate(concat_ws('','[',gal.id,'{'),@ids),(@path:=insert(@path,substring(@ids,@tmp+length(gal.id)+2,locate('}',@ids,@tmp)-@tmp-1)-1,length(gal.name)+2,concat_ws('',' ',gal.name,' '))),('1'))='');

select @aim as aim, @path as path;

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

если вдруг найдутся сильно интерисующиеся, но ленивые, могут выложить схему таблицы, на которой тестировалось, но вообще она и так очевидна из запроса
















Смотрите также:

No related posts.