Mysql分层查询忽略了重复的行(但它不应该!)

时间:2011-07-22 00:28:13

标签: php mysql

我试图将一个谱系放在一个包含狗ID,名字,Sire_ID,Dam_ID的表中。所有的狗都在这张桌子里。我在sitepoint找到了一个漂亮的功能,但它有一个问题,一只狗可以拥有相同的祖父母由于线性繁殖。如果发生这种情况,此功能不起作用:

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

$ idsx可能如下所示:(25,65,42,36,99,29,72,25)。由于ID#25在那里两次,它第二次被忽略,我的血统破裂了。反正有没有让它总是返回所有行?

这是完整的功能:

    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);
}

调用功能/输出结果:

$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";
}

更新功能:

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);
}

3 个答案:

答案 0 :(得分:1)

尝试此更改:

// 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 ";

答案 1 :(得分:0)

25是否在该阵列中一次,两次或二十次并不重要。 IN()只需要知道它就在那里。

您可能希望查看FIND_IN_SET()功能

答案 2 :(得分: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];
}