PDO: получить все непроверенные карточки из базы данных

Я пытаюсь получить все карточки из определенной колоды (deck_id), которые находятся в ожидании.

Флэш-карты в ожидании, когда

  • он не был протестирован,
  • next_review не установлен (новая карта) или
  • next_review <= $today (означает, что карта должна быть рассмотрена).

В настоящее время я получаю результаты из разных колод карт, таких как deck_id 1иdeck_id 2, но я просто хочу получить ожидающие карты из той же колоды (например deck_id = 1).

Это то, что я пытался:

//Get the untested and ready to review cards from DB
public function getCardSR($deckId)
{

    $today = date('Y-m-d');
    $notSet = '0000-00-00';

$query = "SELECT tbl_repetition.repetition_id, 
                 tbl_repetition.card_id, 
                 tbl_repetition.deck_id, 
                 tbl_repetition.user_id, 
                 tbl_repetition.status, 
                 tbl_repetition.last_review, 
                 tbl_repetition.eFactor, 
                 tbl_repetition.inter, 
                 tbl_repetition.repetition, 
                 tbl_repetition.grade, 
                 tbl_cards.front, 
                 tbl_cards.back
    FROM tbl_repetition
    LEFT JOIN tbl_cards
    ON tbl_repetition.card_id = tbl_cards.card_id
    WHERE tbl_repetition.deck_id = :deckId AND 
          tbl_repetition.next_review <= :today OR 
          tbl_repetition.next_review = :notSet";

    $stmt = $this->conn->prepare($query);
    $stmt->bindParam(':deckId', $deckId);
    $stmt->bindParam(':today', $today);
    $stmt->bindParam(':notSet', $notSet);
    $stmt->execute();

    $result = $stmt->fetchAll();

    return $result;
}   

Таким образом результаты извлекаются из $resultмассива:

$repetition_id = $decks->getCardSR($c)[$repetitionCard]  ["repetition_id"];
$eFactor =       $decks->getCardSR($c)[$repetitionCard]["eFactor"];
$card_id =       $decks->getCardSR($c)[$repetitionCard]["card_id"];
$deck_id =       $decks->getCardSR($c)[$repetitionCard]["deck_id"];
$user_id =       $decks->getCardSR($c)[$repetitionCard]["user_id"];
$status =        $decks->getCardSR($c)[$repetitionCard]["status"];
$last_review =   $decks->getCardSR($c)[$repetitionCard]["last_review"];
$inter =         $decks->getCardSR($c)[$repetitionCard]["inter"];
$repetition =    $decks->getCardSR($c)[$repetitionCard]["repetition"];
$grade =         $decks->getCardSR($c)[$repetitionCard]["grade"];
$front =         $decks->getCardSR($c)[$repetitionCard]["front"];
$back =          $decks->getCardSR($c)[$repetitionCard]["back"];

1 ответ

  1. Ваша проблема исходит из приоритета оператора в вашем WHEREпредложении.

    Теперь вы делаете это :

    WHERE tbl_repetition.deck_id = :deckId AND 
          tbl_repetition.next_review <= :today OR 
          tbl_repetition.next_review = :notSet
    

    Назовем первое выражение 1, второе 2 и третье 3.

    Это означает, что он будет оцениваться следующим образом :

    1. AND будет оценено сперва, поэтому оно сделает (1 AND 2)
    2. OR будет оценено второе, поэтому вы приведете в (1 AND 2) OR 3

    Это означает, что вы получите все карты из одной колоды, которые нужно просмотреть сегодня, и все карты из всех колод, которые не установлены…

    Чтобы решить эту проблему, вы должны поместить скобки, чтобы сделать ORоцениваться в первую очередь :

    WHERE tbl_repetition.deck_id = :deckId AND 
          (tbl_repetition.next_review <= :today OR 
          tbl_repetition.next_review = :notSet)
    

    Таким образом, вы будете иметь то, что вы хотите