【问题标题】:Correlated Subquery help in MySQLMySQL 中的相关子查询帮助
【发布时间】:2011-12-20 05:38:34
【问题描述】:

我需要找到表中每个 ID 的最后一行,其中指示“是”,然后在同一个表中搜索该 ID 的下一个实例,以确保该条目为“否”。目前,这在与使用第二个 where 子句中第一个查询的结果的 php foreach 结合的查询中工作得很好。数据集只有 3000 多行,整个过程在 4 多分钟内完成,效率极低。

我知道只有当我只有一个 Where 条件时我才能使用 sql 执行此操作,但由于我有两个条件,我似乎遇到了困难,感谢我能得到的任何帮助。

提前致谢。

//Get max dispatchID where Available = 'Yes'
    <?php $sql = "SELECT a.memberID, MAX(a.dispatchID) as lastDispatchIDYes
                FROM  members_availability a
                WHERE available = 'Yes'
                GROUP BY memberID";
    $qry = $this->db->query($sql);              
    foreach($qry->result() as $row){
        $sql2 = "SELECT dispatchID, memberID, 
                     FROM members_dispatch WHERE memberID = '".$row->memberID."' AND dispatchID > '".$row->lastDispatchIDYes."' AND available = 'No'ORDER BY dispatchID ASC LIMIT 1";   
        $qry2 = $this->db->query($sql2);
        if($qry2->num_rows() > 0){                  
            echo $row->memberID." switched availability at ".$row->dispatchID."<br />";
        }           
    } ?>

【问题讨论】:

    标签: php mysql sql correlated-subquery


    【解决方案1】:

    这是解决您问题的一个想法。

    select tableNo.*
    from
        (SELECT a.memberID, MAX(a.dispatchID) as lastDispatchIDYes
        FROM  members_availability a
        WHERE available = 'Yes'
        GROUP BY memberID) tableYes
        (SELECT a.memberID, a.dispatchID as dispatchIDNo
        FROM  members_availability a
        WHERE available = 'No'
        ) tableNo 
    where tableYes.lastDispatchIDYes < tableNo.lastDispatchIDNo AND
          tableYes.memberID = tableNo.memberID
    

    这将获取所有可用 = NO 且 dispatchID 大于可用为 yes 的最后一行的行。

    【讨论】:

    • 感谢 Zohaib,10 分钟后,此查询超时,但看起来就像我一直在尝试的那样。
    • 您是否考虑过在列上添加索引以提高性能。在您的情况下,memberId 和 available 的复合索引可能会有所帮助。
    【解决方案2】:

    如果我了解您的需求,我认为此查询可能会有所帮助:

    SELECT `a1`.`memberID`, `a1`.`lastDispatchIDYes`, `b`.`dispatchID`, `b`.`available`
    FROM (SELECT `a`.`memberID`, MAX(`a`.`dispatchID`) AS `lastDispatchIDYes`
    FROM `members_availability` `a` WHERE `a`.`available` = 'Yes'
    GROUP BY `a`.`memberID`) `a1`
    INNER JOIN `members_availability` `b` ON `b`.`memberID` = `a1`.`memberID` AND `b`.`dispatchID` = `a1`.`lastDispatchIDYes` + 1;
    $qry = $this->db->query($sql);              
    foreach($qry->result() as $row) {
        echo $row->memberID . " switched availability at " . $row->lastDispatchIDYes . "<br />";
    }
    

    此外,问题中提到的代码示例中的“echo”语句似乎存在问题。 $row-&gt;dispatchID 不是结果集中的有效值。我认为应该是$row-&gt;lastDispatchIDYes。没有?

    编辑 1: 更新了查询,以便任何 dispatchID 大于最后一个“Yes”条目的 dispatchID 的条目都可以输入“No”条目。上面的原始查询仅读取 dispatchID 紧随其后的那些“否”条目。

    SELECT DISTINCT `a1`.`memberID`, `a1`.`lastDispatchIDYes`
    FROM (
        SELECT `a`.`memberID`, MAX(`a`.`dispatchID`) AS `lastDispatchIDYes`
        FROM `members_availability` `a`
        WHERE `a`.`available` = 'Yes'
        GROUP BY `a`.`memberID`
        ) `a1`
    INNER JOIN `members_availability` `b`
        ON `b`.`memberID` = `a1`.`memberID`
        AND `b`.`available` = 'No'
    WHERE `b`.`dispatchID` > `a1`.`lastDispatchIDYes`;
    

    希望这会有所帮助!

    【讨论】:

    • 感谢 Abhay,这运行良好且速度超快,但仅返回 3 行,应该有 1200 左右,可能分组或连接不正确,我会继续努力并感谢您的捕获在 echo 语句上。
    • @SheldonPereira,很高兴知道它有效。查询没有任何限制,因此我认为可能只有 3 行与所需条件匹配,即最大 dispatchID 为“是”,下一个 dispatchID 为“否”。但我无法对此发表评论,因为我无法查看数据。如果您需要任何帮助,请随时告诉我:-)
    • 所以问题是 JOIN 标准,您使用 b.dispatchID = a1.lastDispatchIDYes + 1 我实际上需要 b.dispatchID > a.lastDispatchIDYes....通过更正,查询运行但很慢,我正在努力,很好的基础,谢谢。
    • @SheldonPereira,如果“否”条目不一定是最后一个“是”的下一个条目,则可能有另一种编写查询的方法。正如您所提到的,将“=”替换为“>”可能会减慢查询速度。我会尝试在我的回复中解决这个问题。
    • 嘿@SheldonPereira,你能测试一下吗?进展如何?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 2011-07-19
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    相关资源
    最近更新 更多