2008-09-19 2 views
0

У меня есть таблица членов в MySQLКак определить заказ на новый товар?

CREATE TABLE `members` (
    `id` int(10) unsigned NOT NULL auto_increment, 
    `name` varchar(65) collate utf8_unicode_ci NOT NULL, 
    `order` tinyint(3) unsigned NOT NULL default '0', 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB; 

И я хотел бы, чтобы позволить пользователям заказать членам, как им нравится. Я сохраняю заказ в столбце order.

Мне интересно, как вставить нового пользователя в нижнюю часть списка. Это то, что я сегодня:

$db->query('insert into members VALUES (0, "new member", 0)'); 
$lastId = $db->lastInsertId(); 
$maxOrder = $db->fetchAll('select MAX(`order`) max_order FROM members'); 
$db->query('update members 
      SET 
       `order` = ? 
      WHERE 
       id = ?', 
      array(
       $maxOrder[0]['max_order'] + 1, 
       $lastId 
     )); 

Но это не совсем точным, а при наличии нескольких пользователей при добавлении новых членов в то же время, это может произойти в MAX(order) будет возвращать одинаковые значения.

Как вы справляетесь с такими случаями?

ответ

4

Вы можете сделать SELECT, как часть INSERT, например:

INSERT INTO members SELECT 0, "new member", max(`order`)+1 FROM members;

Имейте в виду, что вы собираетесь хотите иметь индекс на order колонке, чтобы сделать SELECT, часть оптимизированной.

Кроме того, вам может потребоваться пересмотреть tinyint для заказа, если только вы не ожидаете иметь только 255 заказов.

Также заказ является зарезервированным словом, и вам всегда нужно будет написать его как `order`, поэтому вы можете рассмотреть возможность переименования этого столбца.

2

Поскольку вы уже автоматически увеличиваете идентификатор для каждого нового члена, вы можете заказать по id.

0

Я не уверен, что понимаю. Если каждый пользователь хочет другой порядок, как вы будете хранить индивидуальные предпочтения пользователя в одном отдельном поле в таблице «members»?

Обычно вы разрешаете пользователям заказывать исходя из естественного порядка полей. Какова цель поля заказа?

0

Обычно я делаю все мои заказы на выбор «по порядку, имени»; Затем я всегда вставляю то же значение для Order (0 или 9999999 в зависимости от того, хочу ли я их первым или последним). Тогда пользователь может изменить порядок, как им нравится.

+0

Я пытаюсь предотвратить наличие двух элементов с одинаковыми значениями «порядок», если они вставлены одновременно. Я вставляю элемент с `order` being '0', а затем попытаюсь найти новое значение` order`, которое еще не было принято, но если 2 пользователя сделают это одновременно, у меня будет 2 равных значения. – 2008-09-19 19:37:36

0

InnoDB поддерживает транзакции. Перед вставкой сделайте оператор «begin», и когда вы закончите сделать фиксацию. См. this article для объяснения транзакций в mySql.

+0

Сделки в порядке , но все же вы не мешаете иметь 2 элемента с тем же «порядком», поскольку у нас есть только один запрос выбора и один запрос обновления. Сделки помогли бы в разных случаях, когда вы сделаете несколько вложений/обновлений ... – 2008-09-19 19:35:33

+0

Вы совершенно правы. Мой ответ не решает вашу проблему. Спасибо за комментарий. – boes 2008-09-23 07:01:48

0

Что вы можете сделать, это создать таблицу с ключами (member_id, position), которая будет сопоставляться с другим member_id. Затем вы можете сохранить заказ в этой таблице отдельно от самого списка участников. (Каждый член сохраняет свой собственный порядок списка, который является тем, что я предполагаю, что вы хотите ...?)

Предположив, что у вас есть таблица членов, как это:

+-----------+--------------+ 
| member_id | name   | 
+-----------+--------------+ 
|   1 | John Smith | 
|   2 | John Doe  | 
|   3 | John Johnson | 
|   4 | Sue Someone | 
+-----------+--------------+ 

Тогда вы могли бы иметь таблицу заказа например:

+---------------+----------+-----------------+ 
| member_id_key | position | member_id_value | 
+---------------+----------+-----------------+ 
|    1 |  1 |    4 | 
|    1 |  2 |    1 | 
|    1 |  3 |    3 | 
|    1 |  4 |    2 | 
|    2 |  2 |    1 | 
|    2 |  3 |    2 | 
+---------------+----------+-----------------+ 

Вы можете выбрать список членов с сохраненным заказом, используя внутреннее соединение.Например:

SELECT name 
FROM members inner join orderings 
    ON members.member_id = orderings.member_id_value 
WHERE orderings.member_id_key = <ID for member you want to lookup> 
ORDER BY position; 

В качестве примера, результат выполнения этого запроса для списка Джона Смита (то есть, где member_id_key = 1) будет:

+--------------+ 
| name   | 
+--------------+ 
| Sue Someone | 
| John Smith | 
| John Johnson | 
| John Doe  | 
+--------------+ 

Вы можете рассчитать позицию для добавления к в нижней части списка, добавив одно к максимальному значению позиции для данного идентификатора.

Смежные вопросы