Выборка соседних записей

Активист

Активист
Команда форума
Выборка соседних записей

Есть каталог - группы (дерево), есть продукты, есть сортировка, нужно вытащить соседние товары (предыдущий и следующий), товаров пока не знаю сколько будет,
возможно очень много.

Структура бд:
Код:
CREATE TABLE `catalogProducts` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `productTitle` tinytext,
  `ownerId` int(10) unsigned NOT NULL default '0',
  `redirect` tinytext,
  `smallDescription` text,
  `fullDescription` text,
  `lang` tinytext,
  `position` int(10) unsigned default '0',
  `productMainPhoto` tinytext,
  `showMainPhoto` enum('1','0') NOT NULL,
  `publicInInformationBlock` enum('0','1') NOT NULL,
  `cost` float default '0',
  `oldcost` tinytext,
  `rest` tinyint(4) NOT NULL default '1',
  `articul` tinytext NOT NULL,
  `age` tinytext,
  `discount` tinyint(4) NOT NULL,
  `date` date NOT NULL,
  `new` tinyint(4) default '1',
  `material` tinytext NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `ownerId` (`ownerId`),
  KEY `ownerIdPPosition` (`ownerId`,`position`),
  KEY `ownerIdPPositionPId` (`ownerId`,`position`,`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251
Столбцы
Код:
ownerId  - группа товара
position - позиция (сортировка) товара, может иметь не уникальные значения в таблице
(что-то вроде 0, 2, 4, 5, 6, 6, 8, 9), юзер стрелками двигает товар, имеет возможность вручную проставить сортировку (целые числа).

Сделал следующие SQL-ники:
Код:
mysql> EXPLAIN SELECT `id` FROM `catalogProducts` WHERE `ownerId` = '3' && `position` <= '1' && `id` != '1' ORDER BY `position` LIMIT 0,1;
+----+-------------+-----------------+------+------------------------------------------------------+---------------------+---------+-------+------+--------------------------+
| id | select_type | table           | type | possible_keys                                        | key                 | key_len | ref   | rows | Extra                    |
+----+-------------+-----------------+------+------------------------------------------------------+---------------------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | catalogProducts | ref  | PRIMARY,ownerId,ownerIdPPosition,ownerIdPPositionPId | ownerIdPPositionPId | 4       | const |    1 | Using where; Using index |
+----+-------------+-----------------+------+------------------------------------------------------+---------------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
Код:
mysql> EXPLAIN SELECT `id` FROM `catalogProducts` WHERE `ownerId` = '3' && `position` >= '1' && `id` != '1' ORDER BY `position` LIMIT 0,1;
+----+-------------+-----------------+------+------------------------------------------------------+---------------------+---------+-------+------+--------------------------+
| id | select_type | table           | type | possible_keys                                        | key                 | key_len | ref   | rows | Extra                    |
+----+-------------+-----------------+------+------------------------------------------------------+---------------------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | catalogProducts | ref  | PRIMARY,ownerId,ownerIdPPosition,ownerIdPPositionPId | ownerIdPPositionPId | 4       | const |    1 | Using where; Using index |
+----+-------------+-----------------+------+------------------------------------------------------+---------------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

mysql>
Но что-то меня смущает, есть ли более правильный вариант решения этой несколько типичной задачи? Может быть стоит лучше хранить данные о соседних товарах в информации о товаре? Обновлять после изменения товаров в группе и их сортировки?
 

zerkms

TDD infected
Команда форума
1. можно убрать !=, всё равно оно не оптимизируется для поиска по B-Tree, и при этом изменив условие <= на <
2. поля int нужно и выбирать как целые числа, убрав кавычки вокруг.

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

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

Активист

Активист
Команда форума
По первому пункту есть проблема, `position`может совпасть у соседних товаров, ибо есть возможность юзера самому указывать их.
Естественно, если бы я зарание знал, что `position` уникален, то без проблем, или например, сортировка по ID была бы.

А по второму - разве сравнение идет как целое со строкой?
 

zerkms

TDD infected
Команда форума
Активист
Даже на этом форуме было изучение ряда случаев, когда именно кавычки вокруг чисел были причиной деградации производительности.
 

Фанат

oncle terrible
Команда форума
zerkms
да ладно
разве не на этапе парсинга запроса оно приводится к нужному типу?

-~{}~ 02.09.10 09:38:

Активист
По первому пункту есть проблема, `position`может совпасть у соседних товаров, ибо есть возможность юзера самому указывать их.
Ну так вообще-то именно эта проблема является ключевой, а не проблема сортировки.

Как юзер собирается проставлять циферки, когда товаров "очень много"?
С какой стати ему вообще дали такую возможность?
Почему при обработке его кривой расстановки умная программа не исправляет его ошибки?
 

Активист

Активист
Команда форума
*****
В контексте обычной сортировки товаров, в группе при выводе, не важно, есть ли дубли, или нет, поскольку, ну поставит он 0,1,2,3,4,5,6,7,7,9,10 - "7,7", отсортируются по ID, юзер и не заметит, с одной стороны, да и не ошибка это, с одной стороны.

> дали такую возможность
Это проще, когда товаров много, а нужно заменить два товара местами, например, 2 и 30, стрелками будешь двигать долго, сначала один потом второй.

В контексте крайних товаров, да, нужно просто сделать все позиции уникальными.
 

zerkms

TDD infected
Команда форума
*****
чисто теоретически - да, практически - были проблемы. искать лично мне лень, если что товарищ Wicked мог бы ткнуть в тред более предметно.
 
Сверху