Ограничьте запрос MySQL четным числом результатов

У меня есть немного PHP-кода, который мне нужен для возврата четного числа результатов из базы данных MySQL. Я использую расширение mysqli для выполнения моего запроса.

Мой код примерно такой на данный момент:

//assume we already have a database connection

$query = "SELECT id 
            FROM movies 
           WHERE publish = 1
             AND showimage = 1
        ORDER BY date DESC
           LIMIT 6";

$result = $connection->query($query);

while ($row = $result->fetch_assoc()) {
    //do some stuff
}

Как видите, я ограничиваю запрос до 6 строк, но при некоторых условиях будет возвращено меньше. Если возвращаются только 3 строки, я хочу выбросить последнюю строку и оставить только 2.

Как я могу сделать это в запросе MySQL или в MySQLi?


person Philip Morton    schedule 17.01.2009    source источник


Ответы (8)


Я бы представил что-то вроде этого:

// row counter
$counter = 1;
// loop through each row
while($row = $result->fetch_assoc()) {
    // If there is more than one row remaining 
    // OR if the current row can be divided by two
    if (($result->num_rows - $counter) > 1 || ($counter % 2)) {
        // result code for even rows
        $counter++;
    } else {
        // break out of the loop
        break;
    }
}
person Ross    schedule 17.01.2009
comment
Ты не можешь просто выкинуть последний? Я только что посмотрел, в PHP есть функция array_pop. Я не программист PHP, но я думаю, что должна быть функция длины и оператор по модулю. - person nasmorn; 22.12.2011

Я бы, вероятно, сделал это на PHP, а не на SQL. В цикле while сохраните счетчик, а когда выйдете из цикла, проверьте, не установлен ли счетчик. Если это нечетно, выбросьте результаты последней итерации.

person Henrik Paul    schedule 17.01.2009

Другой вариант — запросить COUNT и изменить запрос в соответствии с результатом:

SELECT COUNT(*) FROM movies WHERE publish = 1 AND showimage = 1
person wvanbergen    schedule 17.01.2009

Я не человек PHP (прошли годы с тех пор, как я смотрел на него), но....

Росс упоминает об этом, но вы хотите использовать

$result->num_rows

каким-то образом в вашем цикле, который обрабатывает результаты, чтобы сохранить четное количество строк.

person Ken Henderson    schedule 17.01.2009

$maxResults = $result->num_rows;
if( ($maxResults % 2) = 1)
    $maxResults--;

Когда счетчик совпадает с $maxResults, выйти из цикла.

person Community    schedule 17.01.2009

Мой ответ - только mysql, хотя, вероятно, не лучший, но, может быть, крутой. :-)

SELECT size INTO @count FROM (SELECT COUNT(*) as size FROM (SELECT * FROM table LIMIT 6) l) t;
SET @count = @count - (@count % 2);
PREPARE stmt_limit FROM 'SELECT * FROM table LIMIT ?';
EXECUTE stmt_limit USING @count;
DEALLOCATE PREPARE stmt_limit;

Шаги:

  1. В первом выражении я указал, сколько результатов вы действительно получили в переменной @count.
  2. Во втором выражении я уменьшаю переменную на единицу, если она неравномерна.
  3. Подготовьте заявление с вашим запросом и заполнителем для лимита
  4. Казнить ребенка
  5. Освободить, не знаю, нужно ли это

Но кто знает, может быть, это быстрее, чем решения php...

person Sander Versluys    schedule 17.01.2009

Самый простой способ - просто взять две строки за раз:

while($row1 = $result->fetch_assoc() && $row2 = $result->fetch_assoc()) {
    do_something_with($row1);
    do_something_with($row2);
}

(Не человек PHP, но культивирование синтаксиса из других ответов...)

person NickZoic    schedule 18.04.2009

Шарки,

Ваше решение будет работать отлично, но вам нужно немного изменить синтаксис. Смотри ниже.

while(($row1 = $result->fetch_assoc()) && ($row2 = $result->fetch_assoc()))
{ 
    do_something_with($row1); 
    do_something_with($row2); 
} 

В противном случае ваша вторая строка отменит первую строку и не покажет первую. Теперь он будет отображать оба результата. Хорошее простое решение, кстати.

person Eric    schedule 05.04.2010