avenger_msoft
Новичок
Рекурсия. Другие предложения?
Привет всем!
Есть таблица в БД:
Она принимает, скажем следующие значения:
Мне необходимо рекурсивно получить всех братьев определенного родителя. Например 4 имет братьев 8, 14, 17, 19 (Выборка по ADOPTIONPF). А 19 (Обратите внимание ЕГО нет в ADOPTIONPF) имеет братьев 4, 8, 14, 17.
Делал так
Функция $base->GetCol() возвращает массив значений, например: array("0"=>"4", "1"=>"2")
Но это не правильный подход. Т.к. рекурсивный обход проходить по одному из столбцов в базе (поле $type). По логике надо делать два вызова рекурсивной процедуры GetChildren для $type = 0 и для $type = 1 и + в селект добавить WHERE ... CHILDRENFK NOT IN (... здесь значения CHILDRENFK которые уже выбирались из базы) для первого селекта, и практически такая же конструкция для второго селекта WHERE ... ADOPTIONPF NOT IN (... здесь значения ADOPTIONPF которые уже выбирались из базы), для того что-бы рекурсия не зацыклилась.
Тогда все как-то грамоздко получится. Есть другие предложения?
-~{}~ 02.05.06 13:44:
Задача решена следующим образом
Может есть другие предложения, более рациональные?
Привет всем!
Есть таблица в БД:
PHP:
CREATE TABLE Childrens (
AdoptionPF INTEGER NOT NULL,
ChildrenFK INTEGER NOT NULL,
CONSTRAINT PF_Childrens PRIMARY KEY (AdoptionPF, ChildrenFK)
);
PHP:
ADOPTIONPF CHILDRENFK
4 8
8 14
8 17
17 19
Делал так
PHP:
function GetChildren($id, &$child_array, $type = 0) {
global $base;
if ($id > 0) {
if ($type == 0 ) {
$child_array[] = $base->GetCol("SELECT CHILDRENFK FROM CHILDRENS WHERE ADOPTIONPF = $id") or Halt($base->ErrorMsg());
} else {
$child_array[] = $base->GetCol("SELECT ADOPTIONPF FROM CHILDRENS WHERE CHILDRENFK = $id") or Halt($base->ErrorMsg());
}
$cnt = count($child_array) - 1;
if (count($child_array[$cnt]) > 0) {
reset($child_array[$cnt]);
foreach ($child_array[$cnt] as $name => $value) {
GetChildren($value, $child_array, $type);
// GetChildren($value, $child_array, 1);
}
}
}
}
Но это не правильный подход. Т.к. рекурсивный обход проходить по одному из столбцов в базе (поле $type). По логике надо делать два вызова рекурсивной процедуры GetChildren для $type = 0 и для $type = 1 и + в селект добавить WHERE ... CHILDRENFK NOT IN (... здесь значения CHILDRENFK которые уже выбирались из базы) для первого селекта, и практически такая же конструкция для второго селекта WHERE ... ADOPTIONPF NOT IN (... здесь значения ADOPTIONPF которые уже выбирались из базы), для того что-бы рекурсия не зацыклилась.
Тогда все как-то грамоздко получится. Есть другие предложения?
-~{}~ 02.05.06 13:44:
Задача решена следующим образом
PHP:
function GetChildren($id, &$child_array, $type = 0) {
global $base;
if ($id > 0) {
$temp_arr = array();
$add_sql = "";
if ($type == 0 ) {
if (count($child_array) > 0) $add_sql = "AND CHILDRENFK NOT IN (" . implode(", ", $child_array) . ")";
$temp_arr = $base->GetCol("SELECT CHILDRENFK FROM CHILDRENS WHERE ADOPTIONPF = $id $add_sql") or Halt($base->ErrorMsg());
} else {
if (count($child_array) > 0) $add_sql = "AND ADOPTIONPF NOT IN (" . implode(", ", $child_array) . ")";
$temp_arr = $base->GetCol("SELECT ADOPTIONPF FROM CHILDRENS WHERE CHILDRENFK = $id $add_sql") or Halt($base->ErrorMsg());
}
if (count($temp_arr) > 0) {
$child_array = array_merge($child_array, $temp_arr);
reset($temp_arr);
foreach ($temp_arr as $name => $value) {
GetChildren($value, $child_array, 0);
GetChildren($value, $child_array, 1);
}
}
} // if ($id > 0)
}
function GetChildrenAll($id) {
$childrensID = array();
GetChildren($id, $childrensID, 0);
GetChildren($id, $childrensID, 1);
$childrensID = array_unique( array_diff( $childrensID, array($id) ) );
return ($childrensID);
}