Справка Correlated Subquery в MySQL - PullRequest
0 голосов
/ 20 декабря 2011

Мне нужно найти последнюю строку для каждого идентификатора в моей таблице, где было указано «Да», а затем выполнить поиск в той же таблице для следующего экземпляра этого идентификатора, чтобы убедиться, что запись была «Нет». В настоящее время это прекрасно работает в запросе в сочетании с php foreach, который использует результаты первого запроса в предложении where второго. Набор данных составляет чуть более 3000 строк, и весь процесс ужасно неэффективен - чуть более 4 минут до его завершения.

Я знаю, что могу сделать это с помощью 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 />";
        }           
    } ?>

Ответы [ 2 ]

0 голосов
/ 20 декабря 2011

Если я понимаю, что вам нужно, я думаю, этот запрос может помочь:

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->dispatchID не является допустимым значением в наборе результатов. Я думаю, что это должно быть $row->lastDispatchIDYes. Нет * * 1006

РЕДАКТИРОВАТЬ 1: обновил запрос так, чтобы запись «Нет» могла быть у любой записи, для которой dispatchID больше, чем dispatchID последней записи с «Да». Исходный запрос выше считывал только те записи «Нет», для которых сразу был следующий 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`;

Надеюсь, это поможет!

0 голосов
/ 20 декабря 2011

Это идея, чтобы решить вашу проблему.

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.

...