SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 04.12.2009 17:04:58

jurasmi
Участник
Зарегистрирован: 04.12.2009
Сообщений: 7

Поменять две строки (записи) местами.

Господа, необходимо, как можно проще, поменять две строки в таблице местами (чтобы при выводе в html поменялся порядок их следования).

Неактивен

 

#2 04.12.2009 17:17:22

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

В html данные выводятся не в том порядке в каком они находятся в таблице, а в том как вы их выбрали.
Для решения вашей задачи возможны 2 варианта:
1. изменить запрос на выборку
2. изменить сами данные в таблице

P.S. На общий вопрос можно получить лишь общий ответ.

Неактивен

 

#3 04.12.2009 17:28:27

jurasmi
Участник
Зарегистрирован: 04.12.2009
Сообщений: 7

Re: Поменять две строки (записи) местами.

Было принято решение "физически" менять местами строчки в базе.

Неактивен

 

#4 04.12.2009 17:36:57

jurasmi
Участник
Зарегистрирован: 04.12.2009
Сообщений: 7

Re: Поменять две строки (записи) местами.

Конкретнее таблица такая:
в строке сначала идёт id записи, в остальных ячейках идут свойства этой записи (имя, описание, .....).
Есть два id-шника, вот записи с такими id-шниками надо поменять в таблице местами.

Неактивен

 

#5 04.12.2009 17:43:06

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

Насколько я понимаю, "физически" менять местами строчки в базе - записать строку "а" в ту область памяти где раньше была строка "б", а стороку "б" туда где раньше была строка "а".
Даже если вам удасться выполнить это действие, ничего в вашем html скорее всего не измениться smile

См предыдущий ответ, особенно поскриптум.

Неактивен

 

#6 04.12.2009 17:49:07

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

jurasmi написал:

Конкретнее таблица такая:
в строке сначала идёт id записи, в остальных ячейках идут свойства этой записи (имя, описание, .....).
Есть два id-шника, вот записи с такими id-шниками надо поменять в таблице местами.

Т.е. вам нужно поменять местами номера id у этих записей.

UPDATE tablename SET id = xxx WHERE id = id1;
UPDATE tablename SET id = id1 WHERE id = id2;
UPDATE tablename SET id = id2 WHERE id = xxx;

xxx - номер не встречающийся в таблице.

Неактивен

 

#7 04.12.2009 17:49:20

jurasmi
Участник
Зарегистрирован: 04.12.2009
Сообщений: 7

Re: Поменять две строки (записи) местами.

Нужно, чтобы в таблице строчка "А" поменялась местами со строчкой "В" (чтобы эти две строчки шли в таблице в другом порядке).

Отредактированно jurasmi (04.12.2009 17:50:55)

Неактивен

 

#8 04.12.2009 17:55:36

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

А что такое "место" в таблице? Может это как раз и есть номер id?

В принципе, ничто не мешает вам по аналогии с приведенным выше примером обновить не номера id, а другие поля (имя, описание, .....), если вы верите, что в этом случае что-то измениться.

Неактивен

 

#9 04.12.2009 18:03:09

jurasmi
Участник
Зарегистрирован: 04.12.2009
Сообщений: 7

Re: Поменять две строки (записи) местами.

Моя "вера" основана на том, что при запросе к базе данных (для вывода в html) результат выводится строчка за строчкой по порядку (и мне кажется, что в том порядке как строчки расположены в таблице)

$str = "SELECT * FROM mode ";
$modeList = mysql_query($str, __dbconnection__);
while($curMode = mysql_fetch_object($modeList)){
    echo $curMode->name;
}

Неактивен

 

#10 04.12.2009 18:14:38

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

test >create table b (id int not null primary key, p varchar(255));
Query OK, 0 rows affected (0.47 sec)

test >insert into b values(1,'a');
Query OK, 1 row affected (0.09 sec)

test >insert into b values(3,'c');
Query OK, 1 row affected (0.05 sec)

test >insert into b values(2,'b');
Query OK, 1 row affected (0.06 sec)

test >select * from b;
+----+------+
| id | p    |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
+----+------+
3 rows in set (0.00 sec)

Неактивен

 

#11 04.12.2009 18:19:05

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

Как видите данные выводятся не в том порядке в каком вносились в таблицу smile

Т.е. мы пришли к тому с чего начинали, а именно - данные выводятся не в том порядке в каком они находятся в таблице, а в том как вы их выбрали.


В данном случае я конечно схитрил, указав primary key по id, так как знаю, что в случае таких запроса и структуры, оптимизатор mysql станет выбирать данные по индексу.

В вашем случае, для избежания неожиданных результатов, нужно просто явно указать в запросе порядок сортировки:
$str = "SELECT * FROM mode ORDER BY id";

Неактивен

 

#12 04.12.2009 18:26:47

jurasmi
Участник
Зарегистрирован: 04.12.2009
Сообщений: 7

Re: Поменять две строки (записи) местами.

Видимо придётся использовать дополнительное поле, чтобы указывать порядок следования этого элемента.

Неактивен

 

#13 04.12.2009 18:35:45

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

А чем вас не устраивает уже имеющийся id?

Неактивен

 

#14 04.12.2009 18:46:15

jurasmi
Участник
Зарегистрирован: 04.12.2009
Сообщений: 7

Re: Поменять две строки (записи) местами.

Задача сделать структуру на сайте (разделы, папки) и надо, чтобы можно было менять порядок вывода разделов. Буду делать у раздела ещё одно поле, в котором будет указан порядок его вывода на страницу.

Неактивен

 

#15 26.11.2010 16:59:06

LOSKAND
Участник
Зарегистрирован: 26.11.2010
Сообщений: 4

Re: Поменять две строки (записи) местами.

Такая же проблема.
Вывод строк таблицы с сортировкой
$query= "SELECT * FROM forumlist WHERE id ORDER BY gtid ASC ";
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY оставил в покое
Решил сортировать через gtid  где gtid число от 1 и выше.
пол дня убил прогоняя разные варианты поменять строки местами.
а хочу реализовать следующее (теория).
что бы при нажатии на кнупку +1 число в поле gtid повышалось на +1 а в строке расположеной выше одновременно число в gtid уменьшалось на -1.
С повышением на +1 я разобрался а вот как реализовать вторую часть задуманого сообразить не могу.

Подскажите пожалуйста с решением вопроса.

Неактивен

 

#16 26.11.2010 17:33:42

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поменять две строки (записи) местами.

Аааа! Некроманты!!! smile

Прийдется попрограммировать, и написать два запроса — один для увеличения,
второй — для уменьшения. Ну или одну хранимую процедуру, которая будет это
делать.

Неактивен

 

#17 27.11.2010 14:42:56

LOSKAND
Участник
Зарегистрирован: 26.11.2010
Сообщений: 4

Re: Поменять две строки (записи) местами.

может есть какие ни будь примеры?
вариант предложеный vasya работает но не верно

Неактивен

 

#18 27.11.2010 14:51:57

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

? Это про какой вариант речь?

Неактивен

 

#19 27.11.2010 14:58:57

LOSKAND
Участник
Зарегистрирован: 26.11.2010
Сообщений: 4

Re: Поменять две строки (записи) местами.

vasya написал:

UPDATE tablename SET id = xxx WHERE id = id1;
UPDATE tablename SET id = id1 WHERE id = id2;
UPDATE tablename SET id = id2 WHERE id = xxx;

xxx - номер не встречающийся в таблице.

вот про этот




код блока перемещения

if(isset($_GET['movetopic'])) { if ($_GET['movetopic'] !="") {
$move1=$_GET['movetopic']; $where=$_GET['where'];
$s = $_GET['movetopic']+1;
$n = $_GET['movetopic']-1;
if ($where=="0") {$where="0";



mysql_query("UPDATE forumlist SET gtid = '".$s."' WHERE gtid = '".$_GET['movetopic']."' LIMIT 1");
mysql_query("UPDATE forumlist SET gtid = '".$n."' WHERE gtid = '".$_GET['movetopic']."' LIMIT 1");
print"++1";
}else{$where="1";


mysql_query("UPDATE forumlist SET gtid = '".$n."' WHERE gtid = '".$_GET['movetopic']."' LIMIT 1");
mysql_query("UPDATE forumlist SET gtid = '".$s."' WHERE gtid = '".$_GET['movetopic']."' LIMIT 1");
print"--1";
}

Header("Location: forum.php");
exit; }}

Отредактированно LOSKAND (03.12.2010 11:09:24)

Неактивен

 

#20 27.11.2010 15:34:40

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

Пример из серии найдите 10 отличий на рисунке smile
Отличие первое: у меня 3 апдейта, а у вас 2 wink
...

Что касается работоспособности метода:

mysql> select * from a;
+------+-------+
| id   | q     |
+------+-------+
|    1 | one   |
|    2 | two   |
|    3 | three |
+------+-------+
3 rows in set (0.00 sec)

mysql> update a set id=11 where id=1;
Query OK, 1 row affected (0.14 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update a set id=1 where id=2;
Query OK, 1 row affected (0.09 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update a set id=2 where id=11;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from a;
+------+-------+
| id   | q     |
+------+-------+
|    2 | one   |
|    1 | two   |
|    3 | three |
+------+-------+
3 rows in set (0.00 sec)



Что касается вашего кода, то от моего понимания ускользает его смысл.
Пусть у вас есть строка с gtid=x. Первым апдейтом вы увеличиваете значение gtid на 1.
Вторым апдейтом хотите уменьшить значение gtid в строке, где gtid=x. А строка такая есть? Вы ведь предыдущим апдейтом её изменили.

Неактивен

 

#21 27.11.2010 21:13:48

LOSKAND
Участник
Зарегистрирован: 26.11.2010
Сообщений: 4

Re: Поменять две строки (записи) местами.

Спасибо vasya за подсказку
в общем сделал так
mysql_query("UPDATE forumlist SET gtid = '".$n."' WHERE gtid = '".$a."' LIMIT 1");
mysql_query("UPDATE forumlist SET gtid = '".$s."' WHERE gtid = '".$s."' LIMIT 1");
mysql_query("UPDATE forumlist SET gtid = '".$a."' WHERE gtid = '".$n."' LIMIT 1");
при таком раскладе строки поднимает на одну в верх.

Для опускания строк вниз сделал обратное. тоесть так
mysql_query("UPDATE forumlist SET gtid = '".$s."' WHERE gtid = '".$a."' LIMIT 1");
mysql_query("UPDATE forumlist SET gtid = '".$n."' WHERE gtid = '".$n."' LIMIT 1");
mysql_query("UPDATE forumlist SET gtid = '".$a."' WHERE gtid = '".$s."' LIMIT 1");
работает, но опускает до той позиции с которой начили подём.
если же предже не поднимать строку на позицию выше такая комбинация не работает, тоесть не опускается на строку ниже.
Где я мог допустить ошибку?
Забавно то что по идее комбинация должна работать так как у меня значения $a, $n, $s меняются постоянно.

Отредактированно LOSKAND (27.11.2010 21:57:23)

Неактивен

 

#22 28.11.2010 08:32:01

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Поменять две строки (записи) местами.

Сделайте простую тестовую табличку

+------+-------+
| gtid | q     |
+------+-------+
|    1 | one   |
|    2 | two   |
|    3 | three |
+------+-------+


Напишите апдейты в явном виде, заменив переменные на конкретные значения и выполняйте их. После каждого апдейта смотрите содержимое таблицы
select * from `test_table`;

Неактивен

 

#23 08.07.2011 00:28:43

pixmaster
Участник
Зарегистрирован: 08.07.2011
Сообщений: 5

Re: Поменять две строки (записи) местами.

Используя пользовательские переменные можно менять сортировку в два запроса и один входящий параметр, а именно id изменяемой записи (в данном запросе = 5).
Данный запрос запись с id=5 поднимет вверх (sort_pos-1), а запись с sort_pos > чем у записи id=5 опустит вниз.

Структура таблицы
id,pid,sort_pos


SELECT @id:=_menu_item.id, @sort_pos:=_menu_item.sort_pos
FROM menu_item AS _menu_item
LEFT JOIN menu_item ON (menu_item.id=5)
WHERE _menu_item.pid=menu_item.pid
AND
_menu_item.sort_pos > menu_item.sort_pos
ORDER BY menu_item.sort_pos ASC;
UPDATE menu_item SET sort_pos=IF(sort_pos=@sort_pos, sort_pos-1, sort_pos+1) WHERE id IN (@id,5);
 


проверки, а нужно ли ваще двигать вверх нету (лень)

Отредактированно pixmaster (08.07.2011 00:37:50)

Неактивен

 

#24 08.07.2011 01:09:15

pixmaster
Участник
Зарегистрирован: 08.07.2011
Сообщений: 5

Re: Поменять две строки (записи) местами.

таки сделал проверку, а так же в зависимости от направления перемещения (вверх или вниз) автоматом вычисляется @dir, теперь только в условии вручную знак менять в зависимости от направления, если вверх то '<' иначе '>'


select @id1:=5;
SELECT @id:=_menu_item.id, @sort_pos:=_menu_item.sort_pos,@count:=COUNT(_menu_item.id),@dir:=_menu_item.sort_pos-menu_item.sort_pos
FROM menu_item AS _menu_item
LEFT JOIN menu_item ON (menu_item.id=@id1)
WHERE _menu_item.pid=menu_item.pid
AND
_menu_item.sort_pos < menu_item.sort_pos
ORDER BY menu_item.sort_pos ASC;
UPDATE menu_item SET sort_pos=IF(@count=0,sort_pos,IF(sort_pos=@sort_pos, sort_pos+(1*@dir), sort_pos-(1*@dir))) WHERE id IN (@id,@id1);

Неактивен

 

#25 10.07.2011 00:10:21

vladislav
Участник
Зарегистрирован: 26.10.2010
Сообщений: 17

Re: Поменять две строки (записи) местами.

На сколько мне известно, +1 вверх или вниз обычно делают следующим способ: Добавляют еще одну колонку для сортировки. Туда при каждом INSERT заносится цифра, которая больше на (10000 например) чем SELECT MAX(sort). По этой колонке и сортируется. При изменении позиции вверх берутся первые 2 значения. которые меньше чем данное, суммируются и делятся на 2. Далее обновляется колонка sort. При сдвиге вниз соответственно первые 2 значения которые больше текущего.

id | name | sort
---------------
1 |name_1| 10000
2 |name_2| 20000
3 |name_3| 30000
4 |name_4| 40000
5 |name_5| 50000

теперь сдвигаем строку 3 на вторую позицию: (20000+10000) / 2 = 15000
в результате:
id | name | sort
---------------
1 |name_1| 10000
2 |name_2| 20000
3 |name_3| 15000
4 |name_4| 40000
5 |name_5| 50000

при выборке ORDER BY sort

У такого подхода есть свои плюсы и минусы. При частом перемещении туда сюда, можно очень быстро прийти к тому, что при делении пополам результат уже не поменяется. Этот способ можно использовать, если в таблице известно примерное кол-во будущих строк и оно не превышает ну например 50.000, так как чем больше шаг при INSERTe, тем чаще можно будет перемещать их.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson