Цикл Do ... while для получения случайной строки из БД - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь, чтобы скрипт случайно выбрал строку из таблицы и продолжал поиск, если она существует в другой таблице.

Код может объяснить это лучше

do {
    // get a random row from table A
    $search = mysqli_query($db, 'SELECT * FROM `a` ORDER BY RAND() LIMIT 1');

    // get the id
    $row = mysqli_fetch_assoc($search);
    $row_id = $row['id'];

    // check table B to see if the row id exists
    $check = mysqli_query($db, 'SELECT `id` FROM `b` WHERE `item` = "' . $row_id . '" LIMIT 1');
    $result = mysqli_num_rows($check);
} while ($result === 1);

Насколько я понимаю, он должен зацикливаться, пока не найдет песню, которая существует в таблице A, но не B, а затем двигаться дальше, и я могу использовать $row_id.

Теперь это работает, но время от времени он возвращается со строкой, которая существует в таблице B

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Не уверен, что ваша ошибка, ваш код выглядит хорошо. Я думаю, что данные в ваших таблицах могут быть проблемой.

Однако, вместо того, чтобы зацикливаться, вы должны попытаться сделать это в одном запросе. Примерно так:

SELECT * FROM `a`
LEFT JOIN `b` ON `a`.`id` = `b`.`item`
WHERE `b`.`item` = NULL
ORDER BY RAND() LIMIT 1
0 голосов
/ 31 октября 2018

С запросом LEFT JOIN было бы проще найти все песни в a, которых нет в b, а затем выбрать случайную из этого списка. Также обратите внимание, что всегда предпочтительнее выбирать столбцы, которые вам действительно нужны, вместо использования *. Основываясь на вашем коде, этот запрос должен работать:

SELECT a.id
FROM a
LEFT JOIN b ON b.item = a.id
WHERE b.id IS NULL
ORDER BY RAND()
LIMIT 1

Затем вы можете удалить цикл do и заменить его на этот код. Примечание. Я добавил проверку, что на самом деле в a есть песня, которой нет в b:

$search = mysqli_query($db, 'SELECT a.id FROM a LEFT JOIN b ON b.item = a.id
                              WHERE b.id IS NULL ORDER BY RAND() LIMIT 1');
// get the id
$row;
if (!$row = mysqli_fetch_assoc($search)) {
    echo "No non-matching songs found!"
    $row_id = 0;
}
else {
    $row_id = $row['id'];
}
0 голосов
/ 31 октября 2018

Почему бы вместо этого не выполнить один запрос, который выбирает случайную строку из таблицы a, которой нет в таблице b? Как правило, запрос внутри цикла является плохой идеей, и его часто можно избежать. Возможно, это не самый эффективный запрос, но он должен работать лучше, чем обход нескольких запросов.

SELECT a.id
FROM a 
WHERE a.id NOT IN (SELECT b.item FROM b)
ORDER BY RAND()
LIMIT 1

Затем выполните запрос, как обычно, и извлеките единственную строку, которую он возвращает.

...