Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Есть база, так скажем ТОП автомобилей.
Назовем ее topauto, в ней несколько столбцов: id(авто приращение) и name.
допустим у меня там 5 строк (5 автомобилей) сортировка пусть будет по id.
1 Логан
2 Дастер
3 Приора
4 Копейка
5 Десятка
Внезапно автомобиль в позиции 4 стал популярен, и его надо сделать 2-рым по списку.
вот так:
1 Логан
2 Копейка
3 Дастер
4 Приора
5 Десятка
Как же это реализовать? хорошо даже если я добавлю новый столбец которому будет название topnum и будет хранить текущую позицию и сортировать я буду по нему, вопроса это все равно не отменяет.
Нужно именно "воткнуть" в нужное место списка (и остальные сдвинуть вниз или вверх), а не поменять местами.
буду благодарен за возможные решения.
Не в сети
Нужно именно "воткнуть" в нужное место списка (и остальные сдвинуть вниз или вверх), а не поменять местами.
В таблице БД нет никакого порядка записей. Обычно кажется, что SELECT без ORDER возвращает строки в том же порядке, в каком они были вставлены (INSERT), но это только кажется и, например, после DELETE строк в начале таблицы и последующей вставкой новых эти самые новые будут идти первыми, а не последними. Более того, после оптимизации таблицы порядок опять может поменяться.
В связи с этим не понятна трудность. Ты же сам и указываешь решение:
хорошо даже если я добавлю новый столбец которому будет название topnum и будет хранить текущую позицию и сортировать я буду по нему, вопроса это все равно не отменяет.
Так и делай: добавляй новое поле, например, position, а в SELECT добавляй ... ORDER BY position DESC.
Не в сети
Так и делай: добавляй новое поле, например, position, а в SELECT добавляй ... ORDER BY position DESC.
У меня на данный момент так и сделано, но сдвигать вниз все записи через цикл, это то еще занятие. Ищу решение проще.
на данный момент остановился на поднятии опускании по одному элементу.
Это конечно дико костыль но другого решения пока что не нашел.
public function topsetget(Request $r,$topget,$up_down)
{
$redirect = $topget;
$all = DB::table('top')->count();//
if($up_down=="up" && $topget!="1"){
DB::table('top')->where('top', $topget)->update(['top' => "100000"]);//который нужен буферим
DB::table('top')->where('top', $topget-1)->update(['top' => "100001"]);//который вышее будем опускать. но пока тоже буферим
DB::table('top')->where('top', "100001")->update(['top' => $topget]);//который был нужен поднимаем вместо буфера выше.
DB::table('top')->where('top', "100000")->update(['top' => $topget-1]);//который был выше опускаем. из буфера.
$redirect = $topget-1;
}else if($up_down=="down" && $topget!=$all){
DB::table('top')->where('top', $topget)->update(['top' => "100000"]);//наоборот.
DB::table('top')->where('top', $topget+1)->update(['top' => "100001"]);
DB::table('top')->where('top', "100001")->update(['top' => $topget]);
DB::table('top')->where('top', "100000")->update(['top' => $topget+1]);
$redirect = $topget+1;
}
return redirect()->route('index', ['#topgo'.$redirect]);
Не в сети
на данный момент остановился на поднятии опускании по одному элементу.
Да, решение так себе. Впрочем, средствами БД это одной строкой и не реализовать. На ум приходит два варианта.
Первый - два запроса:
UPDATE SET position = position + 1 WHERE position >= новая позиция;
UPDATE SET position = новая позиция WHERE id = передвигаемая запись;
Если выполнять внутри одной транзакции, то не вижу ограничений у этого способа, разве что в гипотетическом будущем счетчик position может переполниться.
Второй - экзотический. UPDATE с разными значениями на нескольких записях делать нельзя, но можно сделать ход конем: использовать стандартные функции SQL, чтобы по id записи получить ее положение.
Для начала выбираешь все записи вообще: SELECT * FROM
Затем сортируешь их как угодно на стороне PHP.
А затем меняешь position для всех одним запросом:
UPDATE SET position = INSTR(" <?=join(" ", array_column($sorted, "id"))?> ", " " || id || " ");
Таким образом, генерируешь строку из id в порядке, в котором их записи должны идти, а UPDATE ставить position так, что чем ближе id к началу строки - тем его position будет меньше. Соответственно, первый элемент будет с position = 2, а последний - с самой большой position.
Этот метод, однако, не безопасный с точки зрения одновременного доступа, да и медленный.
Не в сети
Страницы 1