Программирование => БД (SQL и пр.) => Тема начата: crazy_man от 11 Июнь 2012, 04:16:53
Название: Изменение порядка отображения материала на сайте
Отправлено: crazy_man от 11 Июнь 2012, 04:16:53
Всем доброго. Подскажите пожалуйста тупому :) Как грамотно сделать изменение порядка отображения материала на сайте.. Имеется админка, в которой хочу прикрутить чтоб админ мог определять в каком порядке юзер видит материал..
Хочу сделать листбокс в котором перечислены материалы, и при апдейте в таблицу записывался нужный order. Вся проблема в пересчете order\'ов
Сейчас зделано так: листбокс: \"Порядок отображения материала на сайте (после)\", value в котором равно индексу материала, т.е.Код PHP
Код: php
select id, name from material order by position ->
При выборе материала из списка я конвертирую id в order и прибавляю к нему единицу:
Код: php
list($order)=mysql_fetch_array(mysql_query(\"select position from material where id=\".(int)$_POST[order])); $order++;
Имено так (в листбоксе материалы расположены не по order, а по id) я сделал потому, что сейчас колока order у всех материалов = 0.
Впринципе, на первый взгляд работать будет. Но косячно. Будут поялвятся материалы с дублирующимся значением order, а это не есть хорошо.
Как бы избежать дублирования (одинаковых значений) в order ? Или вообще как правильно это сделать ?
Уже весь мозг себе сломал)))
Название: Изменение порядка отображения материала на сайте
Отправлено: nlive от 14 Июнь 2012, 03:59:47
Ухх... Прежде всего тебе нужно заполнить колонку order (сделать это можно через ROWNUM, но т.к. в MySQL нет такой ф-ции можно изобрести простой счетчик записей )
Сделать это можно так:
Код: sql
set @rownum:=0; update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services order by services.position) p SET s.position = p.rownum WHERE s.id = p.id
Так... Это сделалали. Теперь для этой задачи нам нужно знаю текущую ($oldpos) и новую ($newpos = у тебя order походу) позиции материала. Ну текущую я думаю как узнать объяснять не нужно )))
А теперь сравниваем. Если новая позиция меньше текущей, то запрос будет следующим:
Код: sql
set @rownum:=0; select p.rownum, s.id, s.name, s.position from services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p WHERE (s.id = p.id and s.position = p.rownum and s.position >= 2)
где rownum = это счетчик записей
т.к. нам надо впихнуть новую запись, то новая позиция у нас будет s.position = p.rownum + 1:
Код: sql
set @rownum:=0; update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p SET s.position = p.rownum + 1 WHERE (s.id = p.id and s.position = p.rownum and s.position >= 2)
Если же новая позиция больше текущей, то делаем тоже самое, только к rownum ничего отнимать и прибавлять не нужно:
Код: sql
set @rownum:=0; update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p SET s.position = p.rownum WHERE (s.id = p.id and s.position = p.rownum+1 and s.position <= 5)
Проверка:
Код: sql
set @rownum:=0; select p.rownum, s.id, s.name, s.position from services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p WHERE (s.id = p.id and s.position = p.rownum+1 and s.position <= 5)
Это всё хорошо, только в php эти запросы использовать не очень удобно :) Упростим: Итак, мы знаем что: Если новая позиция больше или равна текущей, то к счетчику ничего не прибавляем, т.е. set s.position = p.rownum + 0) [если oldpos=2, newpos=5] Если новая позиция меньше текущей, то к позиция=счетчику+1, т.е. set s.position = p.rownum + 1) [в случае oldpos=5, newpos=2] Также поступаем и новой записью - счеткик+1 и oldpos в таком случае будет max(s.position)
Теперь собственно сам запрос. Сначала селект
Код
set @rownum:=0; select p.rownum, s.id, s.name, s.position from services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p WHERE (s.id = p.id and s.position between least(2,5) and GREATEST(2,5))
Потом апдейт:
Код: sql
set @rownum:=0; update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p set s.position = p.rownum + 1 WHERE (s.id = p.id and s.position between least(2,5) and GREATEST(2,5))
или так:
Код: sql
set @rownum:=0; update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p set s.position = p.rownum + {$pos} WHERE (s.id = p.id and s.position between least({$oldpos},{$newpos}) and GREATEST({$oldpos},{$newpos}))
Название: Изменение порядка отображения материала на сайте
Отправлено: nlive от 14 Июнь 2012, 11:49:23
Ещё есть вариант reorder со стрелочками, я не пробовал, но судя по коду - он вполне жизнеспособный
Код: php
// $_GET[\'action\'] will indicate up/dn $action = isset($_GET[\'action\']) ? $_GET[\'action\'] : false; // condition input and set default // $_GET[\'id\'] is the id to move up/dn $id = isset($_GET[\'id\']) ? (int)$_GET[\'id\'] : false; // condition input and set default if(!$id){ die(\"No id supplied\"); } if($action <> \"up\" && $action <> \"dn\"){ die(\"Invalid action selected\"); }
list($get_position)=mysql_fetch_array(mysql_query(\"SELECT position FROM $table_name[0] WHERE id = $id\"));
if($action == \"up\"){ // get the id and position of that and the next lower position $query = \"SELECT id, position FROM $table_name[0] WHERE position <= $get_position ORDER BY position DESC LIMIT 2\"; } else { // get the id and position of that and the next higher position $query = \"SELECT id, position FROM $table_name[0] WHERE position >= $get_position ORDER BY position LIMIT 2\"; }
$result = mysql_query($query) // test how many rows (if less than 2, there is no locaiton to move to) if(mysql_num_rows($result) < 2){ echo \"You are already at the limit \"; } else { // move up/dn one by swapping the position values $row1 = mysql_fetch_assoc($result); // row1 $row2 = mysql_fetch_assoc($result); // row2 // update row1 (with row2\'s position value) $query = \"UPDATE $table_name[0] SET position = {$row2[\'position\']} WHERE id = {$row1[\'id\']}\"; $result = mysql_query($query) // update row2 (with row1\'s position value) $query = \"UPDATE $table_name[0] SET position = {$row1[\'position\']} WHERE id = {$row2[\'id\']}\"; $result = mysql_query($query) } }