2011-07-22 2 views
1

Je suis en train de mettre un pedigree ensemble d'une table qui contient l'identification des chiens, Name, Sire_ID, Dam_ID. Tous les chiens sont dans cette table. J'ai trouvé une belle fonction au sitepoint, mais il y a un problème, un chien peut avoir les mêmes grands-parents à cause de la consanguinité. Si cela se produit, cette fonction ne fonctionne pas à cause de cela:Mysql requête hiérarchique ignore les lignes en double (mais il ne devrait pas!)

$sql = "SELECT name, sire_id, dam_id FROM dogs WHERE id IN($idsx)"; 

$ idsx pourrait ressembler à ceci: (25, 65, 42, 36, 99, 29, 72, 25). Puisque l'ID # 25 est là deux fois, il est ignoré la deuxième fois et mon pedigree se casse. Y at-il de toute façon pour le faire toujours retourner toutes les lignes?

Voici la fonction complète:

function query_ancestors($ids,$generation){ 
    // Make sure we have some doggies to look up 
    $results = array(); 
    if (count($ids) < 1) return $results; // No more ancestors 
    // For storing parent ids 
    $parentIds = array(); 
    // Query all of the current generation 
    $idsx = implode(',',$ids); // Makes comma delimited string 
    $sql = "SELECT name, sire_id, dam_id FROM dogs WHERE id IN($idsx)"; 
    $rows = mysql_query($sql); 
    while ($row = mysql_fetch_assoc($rows)){ 
     // Add to results 
     $row['generation'] = $generation; 
     $results[] = $row; 
     // Find the parents 
     if ($row['sire_id']) $parentIds[] = $row['sire_id']; 
     if ($row['dam_id']) $parentIds[] = $row['dam_id']; 
    } 
    // repeat for all the parent dogs 
    $generation++; 
    $resultsx = query_ancestors($parentIds,$generation); 
    return array_merge($results,$resultsx); 
} 

fonction d'appel/Résultats de sortie:

$generation = 0; 
$ids = array(8); // id of the the dog to start with 
$results = query_ancestors($ids,$generation); 
foreach($results as $result){ 
    echo "{$result['generation']} {$result['id']} {$result['name']} <br>\n"; 
} 

fonction Mise à jour:

function query_ancestors($ids,$generation){ 
    // Make sure we have some doggies to look up 
    $results = array(); 
    if (count($ids) < 1) return $results; // No more ancestors 
    // For storing parent ids 
    $parentIds = array(); 
    // Query all of the current generation 
    $current_gen_ids = implode(',',$ids); // Makes comma delimited string 
    $sql = "SELECT dog_name, dog_sire_id, dog_dam_id FROM dogs JOIN (UNION ALL SELECT $current_gen_ids AS dog_id) AS idsx ON idsx.dog_id = dogs.id"; 
    $rows = mysql_query($sql); 
    while ($row = mysql_fetch_assoc($rows)){ 
     // Add to results 
     $row['generation'] = $generation; 
     $results[] = $row; 
     // Find the parents 
     if ($row['dog_sire_id']) $parentIds[] = $row['dog_sire_id']; 
     if ($row['dog_dam_id']) $parentIds[] = $row['dog_dam_id']; 
    } 
    // And here is the trick, repeat for all the parent dogs 
    $generation++; 
    $resultsx = query_ancestors($parentIds,$generation); 
    return array_merge($results,$resultsx); 
} 

Répondre

1

Essayez ce changement:

// Query all of the current generation 
// Makes a table to be used for JOIN 
$idsx = 'SELECT ' . implode(' AS id UNION ALL SELECT ', $ids) . ' AS id' ; 

$sql = "SELECT dog_name, dog_sire_id, dog_dam_id FROM dogs JOIN (" 
     . $idsx . ") AS idsx ON idsx.id = dogs.id "; 
+0

Quand j'ai essayé ce j'ai eu un « imploser() [function.implode]: Les arguments non valides passé ". Je ne suis pas sûr de ce qui se passe, alors j'ai essayé de casser un peu plus les choses. Maintenant j'ai un SQL invalide (Vous avez une erreur dans votre syntaxe SQL, vérifiez le manuel correspondant à votre version du serveur MySQL pour la bonne syntaxe à utiliser près de 'UNION ALL SELECT 367, 391 AS dog_id) AS idsx ON idsx.dog_id = chiens .id LIMIT 0, 'à la ligne 1). Aussi, j'ai mis à jour mes noms de colonnes avec un préfixe "dog_", désolé pour toute confusion. J'ai édité le message original avec le nouveau code. – Brandon

+0

@Brandon: Mon tort. Essayez maintenant. Mon code essaie de connaître la requête comme: '... FROM chiens JOIN (SELECT 25 AS id UNION ALL SELECT 73 AS id ... UNION ALL SELECT 25 AS id) AS idsx ON idsx.id = dogs.id' Le' UNION ALL' conservera (et rejoindra) les ID en double. –

+0

Oh, je vois ce que tu fais! Fonctionne très bien. C'est rapide aussi. Merci un million! – Brandon

0

Peu importe si 25 est dans ce tableau une fois, deux fois, ou vingt fois. IN() seulement besoin de savoir qu'il est là du tout.

Vous voudrez peut-être regarder la fonction FIND_IN_SET() à la place

0
$sql = "SELECT name, sire_id, dam_id FROM dogs WHERE id IN($idsx)"; 
$rows = mysql_query($sql); 
$intermediate = array(); 
while ($row = mysql_fetch_assoc($rows)){ 
    // Add to results 
    $row['generation'] = $generation; 
    // Find the parents 
    $intermediate[$row['id']] = $row; 
} 
foreach($ids as $id){ 
    if ($intermediate[$id]['sire_id']) $parentIds[] = $intermediate[$id]['sire_id']; 
    if ($intermediate[$id]['dam_id']) $parentIds[] = $intermediate[$id]['dam_id'];  
    $results[] = $intermediate[$id]; 
} 
Questions connexes