Как я могу изменить порядок строк в базе данных SQL
Можно ли изменить порядок строк в базе данных SQL? Например; как я могу поменять местами порядок значений 2-го ряда и 3-го ряда?
Порядок строки важен для меня, так как мне нужно отобразить значение в соответствии с порядком.
Спасибо за ответы на все вопросы. Но "Заказ по" не будет работать для меня.
Например, я положил список закладок в базу данных. Я хочу отобразить на основе результата, который я получаю из запроса. (не в алфавитном порядке). Просто когда они вставлены.
Но пользователь может изменить расположение закладки (любым способом, который он / она хочет). Поэтому я не могу использовать "заказ по".
Например, как закладка отображается в закладке в Firefox. Пользователь может легко менять положение. Как я могу упомянуть это в БД?
Спасибо.
18 ответов
Похоже, вам нужен еще один столбец, как "ListOrder". Таким образом, ваш стол может выглядеть так:
BookMark ListOrder
======== =========
d 1
g 2
b 3
f 4
a 5
Затем вы можете "заказать" ListOrder.
Select * from MyTable Order By ListOrder
Если пользователь может перемещать закладку только по одному месту за раз, вы можете использовать целые числа в качестве ListOrder и поменять их местами. Например, если пользователь хочет переместить "f" на одну строку вверх:
Update MyTable
Set ListOrder=ListOrder+1
Where ListOrder=(Select ListOrder-1 From MyTable where BookMark='f')
Update MyTable
Set ListOrder=ListOrder-1
Where BookMark='f'
Если пользователь может переместить закладку вверх или вниз на несколько строк одновременно, вам необходимо изменить порядок сегментов. Например, если пользователь хочет переместить "f" в начало списка, вам необходимо:
update MyTable
Set ListOrder=ListOrder+1
where ListOrder>=1 -- The New position
and ListOrder <(Select ListOrder from MyTable where BookMark='f')
update MyTable
Set ListOrder=1 -- The New Position
Where Bookmark='f'
Как уже упоминали другие, не стоит полагаться на физический порядок таблицы базы данных. Реляционные таблицы концептуально больше похожи на неупорядоченные множества, чем упорядоченные списки. Предполагая определенный физический порядок может привести к непредсказуемым результатам.
Похоже, что вам нужно, это отдельный столбец, в котором хранится предпочтительный порядок сортировки пользователя. Но вам все равно нужно будет что-то сделать в своем запросе, чтобы отобразить результаты в указанном порядке.
Можно указать физический порядок записей в базе данных, создав кластеризованный индекс, но это не то, что вы хотели бы делать на произвольной основе, определенной пользователем. И это все еще может привести к неожиданным результатам.
Использование ORDER BY
в вашем SELECT
запрос. Например, чтобы заказать по фамилии пользователя, используйте:
SELECT * FROM User ORDER BY LastName
Порядок строк в фактической базе данных не должен иметь значения.
Вы должны использовать ORDER BY
пункт в ваших запросах, чтобы заказать их, как вам нужно.
Немного поздно на вечеринку, но всем, кто все еще ищет ответ на эту проблему, нужно использовать технику Штерна-Брокота.
Вот статья, объясняющая теорию, лежащую в основе этого
Для каждого элемента нужно сохранить числитель и знаменатель. Затем вы также можете добавить вычисляемый столбец, который является делением обоих. Каждый раз, когда вы перемещаете элемент между двумя другими, числитель элемента становится суммой обоих соседних числителей, а знаменатель элемента становится суммой обоих соседних знаменателей.
Эти числа не будут расти так быстро, как при использовании метода «усреднения», когда вы теряете всю точность после 17 перестановок.
Я также создал демонстрацию, в которой реализован метод.
Базы данных могут хранить данные любым удобным для них способом. Использование предложения order by - единственный способ гарантировать порядок данных. В вашем примере закладки вы могли бы иметь целочисленное поле, которое указывает порядок, а затем обновлять это поле, когда пользователь перемещает вещи. Затем закажите этот столбец, чтобы получить все в правильном порядке.
У меня есть решение для этого, которое я использовал несколько раз. Я сохраняю дополнительное поле "sort_order" в таблице и обновляю его при переупорядочении. Я использовал это в тех случаях, когда у меня есть какие-то контейнеры с элементами, и порядок элементов должен быть редактируемым внутри контейнера. При переупорядочении я обновляю sort_order только для элементов в текущем контейнере, что означает, что не нужно обновлять много (обычно на практике только несколько) строк.
Короче, я делаю следующее:
- добавить поле sort_order в таблицу элементов
- при вставке новой строки я устанавливаю sort_order = id
- при переупорядочении (нужен идентификатор элемента для перемещения и идентификатор элемента для вставки после):
- выберите id, sort_order из элементов, где container = порядок ID по sort_order
- разделить id и sort_order из строк в два массива
- удалить идентификатор элемента для перемещения из списка идентификаторов
- вставить идентификатор элемента для перемещения после идентификатора элемента для вставки после
- объединить список идентификаторов и список sort_order в двумерный массив, как
[[id, sort_order], [id2, sort_order], ...]
- бежать
update item set sort_order=SORT_ORDER where id=ID
(executemany) с объединенным списком
(Если вы перемещаете элемент в другой контейнер, после обновления "внешний ключ контейнера" переходите первым или последним в зависимости от приложения.)
(Если обновление включает в себя большое количество элементов, я не думаю, что это решение является хорошим подходом.)
Я сделал пример использования python и mysql на http://wannapy.blogspot.com/2010/11/reorder-rows-in-sql-database.html (скопируйте и попробуйте) вместе с некоторыми дополнительными пояснениями.
Я думаю, простой order by
будет то, что вы ищете?
select my_column from my_table order by my_order_column;
Добавить position
столбец к вашей таблице и хранить в виде простого целого числа.
Если вам нужно поддерживать несколько пользователей или списки, лучше всего создать таблицу закладок, таблицу пользователей и таблицу для их связи.
- закладки:
id,url
- пользователей:
id,name
- users_bookmarks:
user_id, bookmark_id, position, date_created
Если предположить, date_created
Заполняется при вставке строк, вы можете получить вторичный порядок списков на основе даты.
select bookmark_id from users_bookmarks where user_id = 1 order by position, date_created;
В такие моменты мне напоминают цитату из "Матрицы": "Не пытайтесь упорядочить базу данных. Это невозможно. Вместо этого, только осознайте правду... порядка нет. Тогда вы увидите, что это таблица, которая заказывает сам, это вы заказываете стол.
При работе с MySQL через графический интерфейс всегда принимается решение. Если вы запускаете что-то вроде SELECT * FROM users
MySql всегда будет принимать решение упорядочить это по некоторому полю. Обычно это будет первичный ключ.
+----------------
| id | name |
-----------------
| 1 | Brian |
| 2 | Carl |
| 3 | Albert |
-----------------
Когда вы добавляете ORDER BY
Команда на запрос, он примет решение упорядочить по какому-либо другому полю.
Например Select * From users ORDER BY name
даст:
+----------------
| id | name |
-----------------
| 3 | Albert |
| 1 | Brian |
| 2 | Carl |
-----------------
Итак, на ваш вопрос вы, похоже, хотите изменить порядок по умолчанию, в соответствии с которым ваша таблица отображает эту информацию. Для этого проверьте, в каком поле находится ваш первичный ключ. Для большинства практических целей наличие уникального идентифицирующего натурального числа имеет тенденцию добиваться цели. MySQL имеет функцию AUTO_INCREMENT для этого. При создании таблицы это будет выглядеть примерно так field_name int NOT NULL AUTO_INCREMENT
,
Все это означает: если вы хотите изменить "порядок строк", вам нужно обновить это значение. Однако, поскольку идентификатор - это то, что другие таблицы будут использовать для ссылки на ваше поле, это выглядит немного безрассудно.
Если вы например пошли: UPDATE table Set id = 1 where id = 2;
изначально это не получится, поскольку поля id будут в конечном итоге идентичными и не пройдут проверку Primary Key (которая требует как уникальности, так и наличия установленного значения). Вы можете манипулировать этим, запустив три оператора обновления подряд:
UPDATE users Set id = 100000000 where id = 1;
UPDATE users Set id = 1 where id = 2;
UPDATE users Set id = 2 where id = 100000000;
Это приведет к тому, что строки для этой таблицы будут выглядеть так:
+----------------
| id | name |
-----------------
| 1 | Carl |
| 2 | Brian |
| 3 | Albert |
----------------+
Что технически будет работать, чтобы переупорядочить эту таблицу, но это в пузыре. MySQL, являющийся реляционной базой данных, означает, что любая таблица, которая в зависимости от этих данных была непротиворечивой, теперь будет указывать на неправильные данные. Например, у меня есть таблица, в которой хранятся дни рождения, ссылающиеся на исходную таблицу пользователей. Это структура может выглядеть так:
+----------------------------+
| id | user_id | birthdate |
+----------------------------+
| 1 | 1 | 1993-01-01 |
| 1 | 2 | 1980-02-03 |
| 1 | 3 | 1955-01-01 |
+----------------------------+
Переключая идентификаторы в пользовательской таблице, вы ДОЛЖНЫ обновить значение user_id в таблице дней рождения. Конечно, MySQL готовится к этому: введите " Ограничения внешнего ключа". Пока вы сконфигурировали все ограничения внешнего ключа для Cascade Updates, вам не нужно будет вручную изменять ссылку на каждое значение, которое вы изменили.
Эти запросы будут много ручной работы и потенциально могут ослабить целостность ваших данных. Если у вас есть поля, которые вы хотели бы регулярно ранжировать и переупорядочивать, ответ Майка Льюиса на этот вопрос с "табличным порядком" был бы более разумным ответом (и если это так, то это его лучшее решение и просто не обращайте внимания на этот ответ).
Как заявили другие, используйте заказ по.
Никогда не зависите от порядка данных в физической таблице, всегда основывайте его на данных, с которыми вы работаете, будь то одно или несколько ключевых полей.
Во-первых, позвольте мне согласиться со всеми здесь, что порядок в таблице не должен иметь значения. Используйте отдельный столбец [SortOrder], который вы обновляете, и включите в него предложение Order By.
Тем не менее, базы данных SQL Server допускают один "кластеризованный индекс" для таблицы, который фактически вынудит положение в хранилище базовой таблицы. В первую очередь полезно, если у вас большой набор данных и вы всегда запрашиваете что-то конкретное.
В вопросе отсутствуют какие-либо подробности, которые позволили бы кому-либо дать вам правильный ответ. Очевидно, что вы можете прочитать записи в память, а затем обновить их. Но это плохо на многих разных уровнях.
Вопрос в следующем. В зависимости от реально реализованной схемы существует логика в том, как записи физически записываются на диск. Иногда они пишутся в порядке вставки, а иногда они вставляются с пробелом между блоками (см. Экстенты).
Таким образом, изменение физического порядка маловероятно без обмена данными столбца; и это оказывает глубокое влияние на различные показатели. Вам остается изменить логический порядок.
Когда я читаю ваше обновление... Мне остается понять, что у вас может быть несколько пользователей, и у каждого пользователя должны быть закладки, которые они хотят заказать. Похоже, вам нужна вторая таблица, которая действует как пересечение между пользователем и закладкой. Тогда все, что вам нужно, это внутреннее соединение и порядок.
Но недостаточно информации, чтобы предложить полное решение.
Вот хранимый сценарий продолжения для увеличения или уменьшения (по одному) в MySQL
Обратите внимание, что MySQL не позволяет вам выбирать в том же запросе, который вы обновляете, поэтому приведенные выше ответы не работают.
Я также установил его, чтобы он возвращал ошибку, если нет элемента выше / ниже, если вы увеличиваете / уменьшаете соответственно.
DELIMITER $$
CREATE PROCEDURE `spReorderSequenceItems` (
IN _SequenceItemId INT,
IN _SequenceId INT,
IN IncrementUp TINYINT,
OUT Error VARCHAR(255)
)
BEGIN
DECLARE CurrentPosition INT;
SELECT Position INTO CurrentPosition
FROM tblSequenceItems
WHERE SequenceItemId = _SequenceItemId;
IF IncrementUp = 1 THEN
IF (
SELECT Position
FROM tblSequenceItems
WHERE Position = CurrentPosition + 1 AND SequenceId = _SequenceId
) THEN
UPDATE tblSequenceItems
SET Position = Position - 1
WHERE Position = CurrentPosition + 1 AND SequenceId = _SequenceId;
UPDATE tblSequenceItems
SET Position = Position + 1
WHERE SequenceItemId = _SequenceItemId;
ELSE
SELECT 'No Item Above' AS _Error INTO Error;
END IF;
ELSE
IF (
SELECT Position
FROM tblSequenceItems
WHERE Position = CurrentPosition - 1 AND SequenceId = _SequenceId
) THEN
UPDATE tblSequenceItems
SET Position = Position + 1
WHERE Position = CurrentPosition - 1 AND SequenceId = _SequenceId;
UPDATE tblSequenceItems
SET Position = Position - 1
WHERE SequenceItemId = _SequenceItemId;
ELSE
SELECT 'No Item Below' AS _Error INTO Error;
END IF;
END IF;
END
$$
DELIMITER ;
Позвони с
CALL spReorderSequenceItems(1, 1, 1, @Error);
SELECT @Error;
В ответ на ваше сообщение, ответ, который вы, возможно, ищете:
Чтобы заказать в хронологическом порядке, добавьте DateAdded
или аналогичный столбец с datetime
или же smalldatetime
тип данных.
На всех методах, которые вставляются в базу данных, убедитесь, что вы вставляете CURRENT_TIMESTAMP
в DateAdded
колонка.
На методы, которые запрашивают базу данных, добавьте ORDER BY DateAdded
в конце строки запроса.
НИКОГДА не полагайтесь на физическое положение в системе базы данных. Это может работать БОЛЬШЕ времени, но определенно не ВСЕ время.
Вопрос об обращении можно решить довольно просто. После того, как вы добавили поле в таблицу и знаетеsort
значение закладки, которую вы хотите переместить, вы можете сделать это таким образом. (Подключение к вашей БД и выполнение запросов любым удобным для вас способом)
<?php // moving the bookmark up
$original_sort = 3;
$newsort = ($original_sort -1);
$query = "UPDATE bookmarks
SET sort = CASE sort
WHEN $newsort THEN $original_sort
WHEN $original_sort THEN $newsort
ELSE sort
END
WHERE sort IN ($newsort, $original_sort);";
Чтобы применить это к предпочтениям пользователя, вам нужно будет создать то, что я называю таблицей соединителей, или таблицу, которую вы используете вLEFT JOIN
заявление.
CREATE TABLE `user_bookmarks` (
`id` int NOT NULL AUTO_INCREMENT,
`bookmark_id` int NULL DEFAULT 0,
`sort` smallint NULL DEFAULT 0,
PRIMARY KEY (`id`),
INDEX `idx_bookmark_id`(`bookmark_id`) USING BTREE
);
Теперь запуститеJOIN
запрос на добавление закладок для этого пользователя.
$query = "UPDATE bookmarks AS b
LEFT JOIN user_bookmarks AS u
ON b.id = u.bookmark_id
SET u.sort = CASE u.sort
WHEN $newsort THEN $original_sort
WHEN $original_sort THEN $newsort
ELSE u.sort
END
WHERE u.sort IN ($newsort, $original_sort);";
Если у вас есть числовой столбец (идентификатор строки, идентификатор транзакции и т. Д.), И это то, что вы ожидаете отсортировать, то если сделать этот столбец первичным ключом, это решит проблему сортировки без необходимости выполнения операторов обновления или запроса к таблице.
Если вы хотите упорядочить записи в таблице в соответствии с вашими конкретными потребностями и если у вас нет поля заказа для записей в таблице, вы можете попробовать следующую опцию:
- Откройте схему базы данных / базу данных с помощью редактора жаб
- Экспортируйте свою таблицу в формате Excel, используя опцию экспорта жаб
- Делайте любые изменения, которые вы хотите сделать в экспортированном Excel . Это очень просто изменить порядок строк в Excel .
- Сохраните Excel и импортируйте его обратно в таблицу с помощью опции импорта жаб.
получить жабу: http://www.quest.com/toad-for-mysql/