Самым простым способом было бы поместить ваш заказ в отдельную таблицу (в данном примере называемую ordering_table
):
id | position
----+----------
1 | 11
2 | 42
3 | 23
etc.
Вышеуказанное означало бы "поставить id
из 1 в позицию 11, 2 в положении 42, 3 в положении 23, ... ".Затем вы можете присоединиться к этой таблице заказов в:
SELECT t.id, t.col1, t.col2
FROM some_table t
JOIN ordering_table o ON (t.id = o.id)
ORDER BY o.position
Где ordering_table
- таблица (как указано выше), которая определяет ваш странный порядок.Этот подход просто представляет вашу функцию упорядочения в виде таблицы (в конце концов, любая функция с конечной областью, по сути, является просто таблицей).
Этот подход «таблицы упорядочения» должен работать нормально, пока таблица упорядочениязавершено.
Если вам нужен только этот странный порядок в одном месте, вы можете объединить столбец position
в основную таблицу и добавить ограничения NOT NULL
и UNIQUE
для этого столбца, чтобы убедиться, что вы охватите всеи иметь последовательный порядок.
Дальнейшее комментирование означает, что вы хотите разные заказы для разных пользователей и категорий и что порядок будет меняться ежедневно.Вы можете создать отдельные таблицы для каждого условия (что может привести к комбинаторному взрыву) или, как советуют Микаэль Эрикссон и ypercube, добавить еще пару столбцов в таблицу заказов для хранения пользователя и категории:
CREATE TABLE ordering_table (
thing_id INT NOT NULL,
position INT NOT NULL,
user_id INT NOT NULL,
category_id INT NOT NULL
);
thing_id
, user_id
и category_id
будут внешними ключами для их соответствующих таблиц, и вы, вероятно, захотите проиндексировать все столбцы в ordering_table
, но стоит несколько минут посмотреть на планы запросов.чтобы увидеть, будут ли индексы привыкать, стоило бы.Вы также можете сделать все четыре столбца первичным ключом, чтобы избежать дублирования.Тогда запрос поиска будет выглядеть примерно так:
SELECT t.id, t.col1, t.col2
FROM some_table t
LEFT JOIN ordering_table o
ON (t.id = o.thing_id AND o.user_id = $user AND o.category_id = $cat)
ORDER BY COALESCE(o.position, 99999)
Где $user
и $cat
- идентификаторы пользователя и категории (соответственно).Обратите внимание, что изменение в LEFT JOIN и добавление COALESCE, позволяющее пропустить строки в ordering_table
, эти изменения будут помещать все, что не имеет указанной позиции в порядке, в конец списка, вместо того, чтобы удалять их изрезультаты полностью.