powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / рекурсивная функция (процедура)
25 сообщений из 43, страница 1 из 2
рекурсивная функция (процедура)
    #35301291
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток вам!
Насколько я понял, рекурсию простым запросом не реализовать, и надо писать хранимую процедуру(функцию) для этого. В этом и прошу собственно у вас помощи.
Древовидная структура, поля id и top отвечают за дерево, есть некое поле isgroup.
так вот, надо посчитать количество записей, у которых isgroup равно 3, начиная от указанного id вглубь дерева
маленький пример
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
id	name 		top	isgroup
------------------------------------
1	самосвалы		0	1
2	катки		0	1
3	большие		1	1
4	средние		1	1
5	малые		1	1
6	фото1		3	3
7	фото2		4	3
8	фото3		5	3
То есть, если применить эту функцию к самосвалам, вернуть надо 3 (3 фотки), если к большим, средним или малым, то 1.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35301506
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хорошо бы глубина груп была бы небольшая фиксированая.
Что-то типа:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
select id, name, count( 1 ) cnt
from (
select id, name, t1.isgroup t1g, t2.isgroup t2g, t3.isgroup t3g, t4.isgroup t4g
from
tbl t1 left join tbl t2 on t1.id = t2.top
        left join tbl t3 on t2.id = t3.top
        left join tbl t4 on t3.id = t4.top ) x
where 
  (t1g= 3 ) or (t2g= 3 ) or (t3g= 3 ) or (t4g= 3 )  -- 3 in (t1g,t2g,t3g,t4g)
group by id  
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35301758
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
не, каталог бесконечный ваще
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35301984
skol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
2.
create function getPicturesCount(aID bigint) returns bigint
return (select sum(isgroup= 3 ) + sum(getPicturesCount(id)) from TABLE1 where top = aID);
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302057
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо, но при попытке сделать
Код: plaintext
select getPicturesCount( 100695 );
выдало ошибку 1424: recursive stored function and triggers are not allowed.
может прав не хватает у юзера? или в функции дело?
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302129
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
хотя у себя из под рута выполнил, прав навалом, то же самое сказал
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302160
Фотография Nick Anikin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
рекурсивно процедуру нельзя вызывать в mysql, делайте через цикл
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302178
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
пожалуйста поясните, как, немного в мускуле понимаю
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302181
Фотография Nick Anikin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
что как? цикл написать?
http://dev.mysql.com/doc/refman/5.0/en/while-statement.html
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302378
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я думал эту функцию как то по другому запустить.
смысл писать тогда рекурсивные функции, если их нельзя запускать..
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302389
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nick Anikinрекурсивно процедуру нельзя вызывать в mysql, делайте через цикл
Можно
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302405
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
xelaok Nick Anikinрекурсивно процедуру нельзя вызывать в mysql, делайте через цикл
Можно
помогите уже )))
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302424
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
djvov xelaok Nick Anikinрекурсивно процедуру нельзя вызывать в mysql, делайте через цикл
Можно
помогите уже )))
Через процедуру делай
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302459
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
2.
CREATE FUNCTION `getPicturesCount`(aID bigint) RETURNS bigint( 20 )
return (select sum(isgroup= 3 ) + sum(getPicturesCount(id)) from foto_foto where top = aID);
function заменить на procedure?
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302555
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
djvov
Код: plaintext
1.
2.
CREATE FUNCTION `getPicturesCount`(aID bigint) RETURNS bigint( 20 )
return (select sum(isgroup= 3 ) + sum(getPicturesCount(id)) from foto_foto where top = aID);
function заменить на procedure?
хз, у меня тока так получилось:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
drop procedure if exists go;
drop function if exists calc;

delimiter |

create procedure go(p_id int, p_isgroup int, in k1 int, out k2 int)
begin
  declare done, l_id, l_isgroup int default  0 ;
  declare cur cursor for 
    select
      id,
      isgroup
    from
      foto_foto
    where
      top = p_id;
  declare continue handler for sqlstate '02000' set done =  1 ;

  set k2 = k1;
  open cur;
    repeat
      fetch cur into l_id, l_isgroup;
      if not done then
        call go(l_id, p_isgroup, k2 + if(l_isgroup = p_isgroup,  1 ,  0 ), k2);
      end if;
    until done end repeat;
  close cur;
end
|

create function calc(p_id int, p_isgroup int) returns int
begin
  declare k int default  0 ;
  call go(p_id, p_isgroup, k, k);
  return k;
end
Код: plaintext
select calc( 1 ,  3 )
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302628
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попрошу кинуть в меня камнем за этот вариант.
Перед тем как ловить камень поясню, рекурсия имеет обыкновение падать при определенном уровне вложенности, а этому абсолютно пофиг.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
delimiter //
create FUNCTION `selectSomething`(recPID INT, recType INT) RETURNS bigint( 20 )
BEGIN
  DECLARE ids BLOB;
  DECLARE tempIDScount INT;
  DECLARE IDScount INT;
  set tempIDScount =  0 ;
  select group_concat(t.id), count(t.id) into ids, IDScount 
	from temptab t 
	where t.top = recPID or t.id=recPID;

	WHILE tempIDScount < IDScount DO
  	set tempIDScount = IDScount;
    select 
			group_concat(t.id), count(t.id) into ids, IDScount
		from 
			temptab t
		where 
			FIND_IN_SET(t.id,ids)	>  0 
			OR FIND_IN_SET(t.top,ids) > 0 ;
  END WHILE;
  return (select count(*) from tempTab where
	FIND_IN_SET(ID,ids)	>  0  and isGroup=recType);						
	
END//
delimiter ;
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302734
Фотография Nick Anikin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MAPA3OTПопрошу кинуть в меня камнем за этот вариант.зачем же камнем? я сразу написал - лучше через цикл переделать :)
MAPA3OTПеред тем как ловить камень поясню, рекурсия имеет обыкновение падать при определенном уровне вложенности, а этому абсолютно пофиг.в mysql даже специальный параметр есть - max_sp_recursion_depth
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302737
Фотография Nick Anikin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xelaok Nick Anikinрекурсивно процедуру нельзя вызывать в mysql, делайте через цикл
Можнода, я неправильно написал, имел ввиду функцию - как хотел автор
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302762
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вообщем скрипт Nick Anikin выдал что Recursive limit 0 (as set by max_sp_recursion_depth variable) was exceeded by routine go
max_sp_recursion_depth надо увеличить? как его указать явно?
Код: plaintext
set @max_sp_recursion_depth= 3000 ;
перед выполнением - не помогло
скрипт MAPA3OT'a на небольшой вложенности работает верно, а на большой - нет.
В архиве дамп базы.
Если считать фотки экскаваторов
Код: plaintext
select selectSomething( 100695 , 3 );
, то будет 13, это верно.
А если считать самосвалы
Код: plaintext
select selectSomething( 100693 , 3 );
, то будет 133, хотя на самом деле там 248.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302784
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nick Anikinв mysql даже специальный параметр есть - max_sp_recursion_depth
Все равно есть максимальное ограничение (255), после которого даже изменение этого параметра не спасет. Опять-таки, если нас устроит некое значение в пределах от 0 до 255, то мы ткнемся в некое подобие этого:
Код: plaintext
1.
2.
ERROR  1436  (HY000): Thread stack overrun:   180628  bytes used of a  262144  byte stack, and
 81920  bytes needed.  Use 'mysqld -O thread_stack=#' to specify a bigger stack.
И будем долго с бубном подбирать нужное значение, поэтому я подумал и послал к черту скорость ради спасения собственных нервов.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302796
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
даже твой скрипт работает быстрей чем та же рекурсия на пхп. еще бы верно посчитала
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302804
skol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MAPA3OTПопрошу кинуть в меня камнем за этот вариант.
Перед тем как ловить камень поясню, рекурсия имеет обыкновение падать при определенном уровне вложенности, а этому абсолютно пофиг.


Минус один - многократный фуллскан таблицы (по числу вложенных уровней), т.е. тормоза
...
как вариант:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
delimiter //
create FUNCTION `selectSomething`(recPID INT, recType INT) RETURNS bigint( 20 )
BEGIN
  DECLARE ids BLOB;
  DECLARE result INT;
  DECLARE childs BLOB;
  DECLARE currentPID char;
  set ids = concat(recPID,',');
  set result =  0 ;
  while length(ids) do
    set currentPID = substring_index(ids,',', 1 );
    set ids = substring(ids,length(currentPID)+ 2 );
    select group_concat(t.id), sum(isGroup=recType) + result into childs, result
	from temptab t 
	where t.top = currentPID;
    if length(childs) >  0  then
      set ids = concat(ids,childs,',');
    end if;
  end while;
  return result;						
END//
delimiter ;
здесь у нас запросы в цикле будут индексированными (при наличии индекса на top), и для каждого ид будут выполнены 1 раз
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302848
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
skol, повис мускуль, 99 процентов нагрузки на камень
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302899
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
djvov, индекс на top установи
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35302912
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
дак поставил перед тем как выполнить
...
Рейтинг: 0 / 0
25 сообщений из 43, страница 1 из 2
Форумы / MySQL [игнор отключен] [закрыт для гостей] / рекурсивная функция (процедура)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]