Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Подбор невесты
 
 автор: Eugene77   (31.03.2012 в 07:39)   письмо автору
 
 

Таблица типа MEMORY содержит 2000 таких строк:
INT id PRIMARY,
INT mother_ID,
INT father_ID

Задача:
Для id = x подобрать одну(любую) невесту не находящуюся с ним в родстве вплоть до 7-го колена.

Разумеется, mother_ID и father_ID - это ссылки id на родителей.



P.S. Spatial итд не надо предлагать.(Для типа MEMORY не подходит)

Кстати, примерно подходящий ответ я встречал на данном форуме когда-то давно (КАК НЕ ХВАТАЕТ ЗАКЛАДОК и ЛИЧНЫХ ЗАМЕТОК) (и номеров страниц тоже)

  Ответить  
 
 автор: Sfinks   (31.03.2012 в 12:05)   письмо автору
 
   для: Eugene77   (31.03.2012 в 07:39)
 

> КАК НЕ ХВАТАЕТ ЗАКЛАДОК и ЛИЧНЫХ ЗАМЕТОК
+1! Подписываюсь!!!
(сори за оффтоп)

  Ответить  
 
 автор: cheops   (31.03.2012 в 14:15)   письмо автору
34.1 Кб
 
   для: Sfinks   (31.03.2012 в 12:05)
 

Окститетесь :))), вон "Добавить закладку" и "мои закладки", хоть подразделы вводите, хоть название тем меняйте, если не нравится, хоть редактируйте...

  Ответить  
 
 автор: Sfinks   (31.03.2012 в 16:18)   письмо автору
 
   для: cheops   (31.03.2012 в 14:15)
 

Винда, падла, имеет свойство слетать в самый неожиданный момент, без возможности восстановления и без шанса сохранить закладки. Помните тему про вирус? А могло и не так все кончиться ) Даже когда переустановка плановая - что-нибудь да забудешь. Поэтому этой функцией пользуюсь исключительно кратковременно.... Чтоб не забыть с чем-нибудь разобраться. Кроме того закладки вечно разбросаны по браузерам, т.к. одним пользоваться не получается. Удаленно хранить - лично я бы пользовался )

  Ответить  
 
 автор: Sfinks   (31.03.2012 в 16:21)   письмо автору
 
   для: Sfinks   (31.03.2012 в 16:18)
 

Тыдышь!!!!
Блин. Ток ща аттач увидел. И ток щас обшарил страницу и разглядел эту ссылку! Оказывается есть )))) Бум пользоваться )))
А я подумал, что вы говорите про "добавить закладку" браузеров )

  Ответить  
 
 автор: cheops   (31.03.2012 в 14:20)   письмо автору
 
   для: Eugene77   (31.03.2012 в 07:39)
 

Одним запросом хотите решить задачу? Без вспомогательных таблиц?

  Ответить  
 
 автор: Eugene77   (31.03.2012 в 15:07)   письмо автору
 
   для: cheops   (31.03.2012 в 14:20)
 

>Одним запросом хотите решить задачу? Без вспомогательных таблиц?

Поскольку речь идёт о временной таблице с парой тысяч строк,
я собирался сделать 5 запросов к таблице рекурсивной функцией на PHP,
выбирая всех прародителей до 7-го колена,

а потом сделать выборку номера невесты, запросом с функцией уже на MySQL,
но не знаю даже... MySQL поддерживает-ли рекурсивные вызовы функций...

Кроме того, в какой форме передать функции массив аргументов, содержащий нежелательные номера?

Мне не обязательно, чтобы красиво, лишь бы работало.
Но вспомогательные таблицы нежелательны: я уже и так в этой базе намучился разбирая что когда и как локировать.
Кроме того, необходимо учитывать, что родительские поля могут быть неопределены(NULL)

  Ответить  
 
 автор: cheops   (01.04.2012 в 13:22)   письмо автору
 
   для: Eugene77   (31.03.2012 в 15:07)
 

Да, MySQL поддерживает рекурсивные вызовы... Можно потом просто создать еще одну таблицу, в которой для каждой строчки по cron-заданию вычисляются прародители до 7 колена, можно это делать один раз в сутки или час - будет некоторая задержка в актуальности, зато все эти рекурсивные задачи сменятся чрезвычайно быстрым поиском по такой промежуточной таблице.

  Ответить  
 
 автор: Eugene77   (03.04.2012 в 07:30)   письмо автору
 
   для: cheops   (01.04.2012 в 13:22)
 

>Да, MySQL поддерживает рекурсивные вызовы...
В смысле: не поддерживает?

Можно потом просто создать еще одну таблицу, в которой для каждой строчки по cron-заданию вычисляются прародители до 7 колена, можно это делать один раз в сутки или час - будет некоторая задержка в актуальности,

В данном конкретном случае задержка по актуальности категорически недопустима.
Так как она разрушает суть генетического алгоритма используемого в данном приложении.

Именно быстрое образование кортких близкородственных линий нарушает статистические критерии выявления наиболее благоприятного эволючионного пути. В данном случае, наоборот, таблицы придётся локировать, пока вопрос родственных связей не будет выяснен.

Я пробовал написать функцию сбора информации о родственниках отца.
Первая версия была рекурсивной - оказалось - MySQL не поддерживает рекурсивные функции.

Вторая версия выглядит вот так:


DROP FUNCTION `ansestors`//
 FUNCTION `ansestors`(child int, parent1 int, parent2 int, maxAnsestorLevel int) RETURNS int(11)
    COMMENT 'Собирает в таблицу fatherrelatives предков s из таблицы points.'
BEGIN
DECLARE p INT;
DECLARE knee INT DEFAULT 0;
DECLARE f INT DEFAULT NULL;
DECLARE m INT DEFAULT NULL;
DECLARE maxIterations INT DEFAULT 2;
DECLARE iterations INT DEFAULT 0;
SET knee = 0;
DELETE FROM fatherrelatives;
IF( child IS NOT NULL ) THEN
    INSERT INTO fatherrelatives SET pointNum = child, knee = knee;
ELSE RETURN 0;
END IF;
IF( parent1 IS NOT NULL ) THEN
    INSERT INTO fatherrelatives SET pointNum = parent1, knee = knee + 1;
END IF;
IF( parent2 IS NOT NULL ) THEN
    INSERT INTO fatherrelatives SET pointNum = parent2, knee = knee + 1;
END IF;
IF( parent1 IS NOT NULL OR  parent2 IS NOT NULL ) THEN
    SET knee = knee + 1;
    IF(knee > maxAnsestorLevel) THEN RETURN knee; END IF;
ELSE
RETURN knee;
END IF;
wet: WHILE knee < maxAnsestorLevel DO
    SELECT pointNum, knee INTO p, knee  FROM fatherrelatives WHERE investigated = 'no' ORDER BY knee LIMIT 1;
    IF( knee > maxAnsestorLevel) THEN
        RETURN knee;
    END IF;
    
    SET iterations = iterations + 1;
    IF(iterations > maxIterations ) THEN
        RETURN knee;
    END IF;
        
    SELECT parent1, parent2 INTO f,  m  FROM points WHERE num = p;
    IF( f IS NOT NULL ) THEN
        INSERT INTO fatherrelatives SET pointNum = f, knee = knee + 1;
    END IF;
    IF( m IS NOT NULL ) THEN
        INSERT INTO fatherrelatives SET pointNum = m, knee = knee + 1 ;
    END IF;
    UPDATE fatherrelatives SET investigated = 'yes' WHERE pointNum = p;
    
END WHILE wet;

RETURN knee;

END



maxIterations - Чтобы избежать зацикливания (на всякий случай)

Смысл в том, что после занесения известных родителей parent1 int, parent2 int,
ищем какие ещё из (ближайших - knee) родственников не исследованы (investigated) на предмет наличия предков и заносим их в таблицу, ставя флаг, что уже исследованы.

Но данная функция не работает,
а как её отлаживать непонятно.
Ошибок не выдаёт, но и родственников нормально не собирает.

  Ответить  
 
 автор: cheops   (03.04.2012 в 12:34)   письмо автору
 
   для: Eugene77   (03.04.2012 в 07:30)
 

>>Да, MySQL поддерживает рекурсивные вызовы...
>В смысле: не поддерживает?
Да от чего такое недоверие? MySQL опирается на уже существующие языки с поддержкой рекурсии и сама она тоже рекурсию поддерживает. Более того, это заложено в любой современный язык программирования, да и вообще любой язык программирования, даже просто язык, без программирования :))).

  Ответить  
 
 автор: Eugene77   (03.04.2012 в 13:55)   письмо автору
 
   для: cheops   (03.04.2012 в 12:34)
 

MySQL опирается на уже существующие языки с поддержкой рекурсии и сама она тоже рекурсию поддерживает.
Это было бы здорово, если бы поддерживалась рекурсия, но тогда в чём конкретно эта поддержка состоит?

Я только вчера получил заявление от MySQL прямым текстом, что рекурсивные вызовы функций недопустимы.
Вам удавалось скормить рекурсивную функцию MySQL?
Тогда очень хотелось бы увидеть этот поучительный пример.

Или речь идёт о чём-то другом?

  Ответить  
 
 автор: cheops   (03.04.2012 в 20:51)   письмо автору
 
   для: Eugene77   (03.04.2012 в 13:55)
 

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

  Ответить  
 
 автор: Eugene77   (04.04.2012 в 08:15)   письмо автору
 
   для: cheops   (03.04.2012 в 20:51)
 

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

А смысл какой?
Если нельзя через возвращаемый аргумент передать то, что насобирали потомки,
то всё надо ссыпать в одну кучку (табличку) - это и без рекурсивного вызова ...

Вообще, что такое рекурсивный вызов процедуры?
В книге вы об этом не писали.
Рекурсивные функции - это общеизвестно, а вот процедуры... да ещё рекурсивные... я просто теряюсь...

Давно-давно когда-то встречал бейсик с процедурами, но тогда у меня ещё соска изо рта выпала и я отвлёкся не успев разобраться что к чему : )

  Ответить  
 
 автор: cheops   (04.04.2012 в 12:39)   письмо автору
 
   для: Eugene77   (04.04.2012 в 08:15)
 

Зависит от книги, но вроде везде старались упоминать. В MySQL два вида (внешне больше, но по внутренней сути два) организации кода:
CREATE FUNCTION - хранимая функция (вызывается как обычная функция)
CREATE PROCEDURE - хранимая процедура (вызывается ключевым словом CALL)
Функция возвращает значение, как традиционная C-функция, в C-подобных языках нет конструкции "процедура", однако, она есть в SQL, более того, много лет назад, когда я знакомился с диалектом SQL в MySQL я дивился, что у них оказывается еще и хранимые функции есть, странно, вроде по стандарту должны быть только процедуры, но стандарты SQL мало где реализованы точно, поэтому заморачиваться не стал. Ситуация мне была знакома, процедуры я знал по Fortran, а функции по C. Если, для вас это в новинку, пожалуйста, обратите внимания, это разные конструкции одного и того же. У них свои собственные заморочки. Функции они вроде как удобнее, особенно для программистов, знакомых с C-подобным языком, но вообще по стандарту SQL положены процедуры - поэтому любая уважающая себя СУБД их реализует.

  Ответить  
 
 автор: Eugene77   (04.04.2012 в 15:46)   письмо автору
 
   для: cheops   (04.04.2012 в 12:39)
 

Благодарю за столь подробный ответ!
Но он не на мой вопрос.
Про процедуры я в вашей книге давно прочитал, но там нет ни одного примера рекурсивного вызова процедуры поэтому я просто не понимаю этого словосочетания.
РЕКУРСИВНЫЕ ПРОЦЕДУРЫ - что подразумевается - ну хоть простейший примерчик!

  Ответить  
 
 автор: cheops   (04.04.2012 в 15:54)   письмо автору
 
   для: Eugene77   (04.04.2012 в 15:46)
 

Книг у нас много, вот в "MySQL: на примерах" я вижу целый подраздел им посвящен, я не очень понимаю, что вызывает сложность, просто вместо хранимый функции (там действительно есть ограничения) создайте хранимую процедуру - их точно можно делать рекурсивными, передавая нужные значения через параметры. Вот допустим рекурсивная процедура удаления каталога (для упрощения без удаления товарных позиций)
CREATE PROCEDURE delcat (IN id INT)
BEGIN
  DECLARE is_end INT DEFAULT 0;
  DECLARE id_cat INT DEFAULT 0;

  DECLARE cat CURSOR FOR 
  SELECT id_catalog FROM catalogs WHERE id_parent = id;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET is_end = 1;

  OPEN cat;
  wet : LOOP
    FETCH cat INTO id_cat;
    IF id_cat > 0 THEN CALL delcat(id_cat);
    END IF;
    DELETE FROM catalogs WHERE id_catalog = id_cat;
    IF is_end THEN LEAVE wet;
    END IF;
  END LOOP wet;
  CLOSE cat;
  DELETE FROM catalogs WHERE id_catalog = id;
END
//

  Ответить  
 
 автор: Eugene77   (04.04.2012 в 16:23)   письмо автору
 
   для: cheops   (04.04.2012 в 15:54)
 

А вот это уже интересно!
Я такого не читал. У меня книга называется просто (MySQL 5).
Спасибо! Буду разбираться

  Ответить  
 
 автор: cheops   (04.04.2012 в 20:46)   письмо автору
 
   для: Eugene77   (04.04.2012 в 16:23)
 

Кстати, возможно вам будет интересно почитать и MySQL на примерах, там много, того, что нет в MySQL 5 (писали позже по уже более свежей версии).

  Ответить  
 
 автор: Eugene77   (05.04.2012 в 16:22)   письмо автору
 
   для: cheops   (04.04.2012 в 20:46)
 

>Кстати, возможно вам будет интересно почитать и MySQL на примерах, там много, того, что нет в MySQL 5 (писали позже по уже более свежей версии).

Да, интересно было бы посмотреть на примеры с курсорами итд.

Но данная тема осталась незакрытой.

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

Но это меньшая часть проблемы: можно было и без рекурсии написать, хотя так код более длинный вышел бы, и, соответственно, дебажить дольше.

Как теперь сделать выборку невесты у которой нет родственников входящих в этот список.

Или выборку с сортировкой по длине родственной связи.

  Ответить  
 
 автор: Eugene77   (05.04.2012 в 16:56)   письмо автору
 
   для: cheops   (04.04.2012 в 20:46)
 

СALL getParentsAndSelf(id, maxKnee);

Возвращает 4 колонки
1 первичный ключ
2 id
3 parent
4 колено - ну, не совсем колено, но на какой ступени пра пра пра находится родственник .(0) - для id=parent

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

  Ответить  
 
 автор: Eugene77   (05.04.2012 в 18:23)   письмо автору
 
   для: cheops   (04.04.2012 в 20:46)
 

Кажется, сообразил примерно во такой запрос надо:

SELECT point FROM points
WHERE NOT EXISTS 
      (
      SELECT point WHERE 
      getParentsAndSelf(point, knee)   IN(Список родителей жениха,включая самого жениха)
      )


Только надо переделать getParentsAndSelf() так, чтобы она возвращала одну колонку родственников.

Если синтаксис вызова процедуры правильный, то, думаю - зто мне и нужно.

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

  Ответить  
 
 автор: Eugene77   (31.03.2012 в 15:29)   письмо автору
 
   для: cheops   (31.03.2012 в 14:20)
 

>Одним запросом хотите решить задачу? Без вспомогательных таблиц?
Допустим, я заполню временную таблицу родственниками жениха,
но как при выборке невесты соотносить её дальних родственников с этой таблицей, я пока сообразить не могу.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования