Mysql: запрос, какие заказы по умолчанию и ранжирование (закрепление / удержание записей?)

#php #mysql #sql #sql-order-by #ranking

#php #mysql #sql #sql-order-by #Рейтинг

Вопрос:

У меня есть таблица продуктов, которая содержит все мои продукты. Таблица этих продуктов постоянно заполняется новыми продуктами. Тем не менее, я хочу иметь возможность «задерживать» / «привязывать» определенные продукты к месту в возвращаемой коллекции запросов.

Означает, что я хочу установить что-то вроде rank_index , которое содержит номер, который должен иметь продукт в возвращаемой коллекции запросов.

Пример:

 id     title                rank_index
1      An awesome product
2      Another product      5
3      Baby car
4      Green carpet         2
5      Toy        
  

Давайте предположим, что порядок по умолчанию будет id . Но поскольку rank_index для продукта установлено значение id 4, я хотел бы получить коллекцию со следующим порядком возвращаемых идентификаторов : 1, 4, 3, 5, 2 .

Возможно ли это как-то сделать? rank_index Столбец был просто моей идеей. Я имею в виду.. Я также мог бы сделать это на php стороне и выполнить обычный запрос, который включает только products без an rank_index и тот, который содержит только products с an index_rank , и упорядочить их вручную на php стороне.

Однако, поскольку это требует много времени и вычислительной мощности, я ищу решение, которое выполняется базой данных… Есть идеи?

Кстати: я использую Laravel 8, если это имеет какое-либо значение.

С уважением

Ответ №1:

Это очень сложная проблема. Если вы попробуете другой подход, устанавливающий последовательные значения — например, 2 и 3 — вы увидите, что они не работают.

Могут быть более простые способы решения этой проблемы. Но вот подход грубой силы.

  1. Он создает производную таблицу путем перечисления строк в исходной таблице.
  2. Он добавляет в эту таблицу (используя a left join ) все значения с принудительным ранжированием.
  3. Он присоединяется к остальным значениям путем перечисления пустых слотов как в table1 производной таблице, так и в ней.

Итак:

 with recursive n as (
      select row_number() over (order by id) as n
      from table1 t1
     ),
     nid as (
      select n.n, t1.id
      from n left join
           table1 t1
           on t1.rank_index = n.n
     ),
     nids as (
      select n.n, coalesce(n.id, t1.id) as id
      from (select nid.*, sum(nid.id is null) over (order by nid.n) as seqnum
            from nid 
           ) n left join
           (select t1.*, row_number() over (order by id) as seqnum
            from table1 t1
            where rank_index is null
           ) t1
           on n.seqnum = t1.seqnum
     )
select t1.*
from nids join
     table1 t1
     on t1.id = nids.id
order by nids.n;
  

Комментарии:

1. Да, этот ответ правильный. Однако к моему новому вопросу я добавил предложение «без рекурсии», а также добавил, что мне нужен id порядок убывания

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

3. @Jan . . . Этот ответ объясняет, что два других ответа неверны.

4. это работает да… вот решение без рекурсии: dba.stackexchange.com/a/279452/218390

5. @Jan . . . Вам нужно настроить тестовые данные, чтобы увидеть, действительно ли что-то работает. Я бы предложил: 2/3; и 1/2 и 4/5 одновременно. У вас есть больше вариантов с более чем 5 слотами.

Ответ №2:

Используйте rank_index if это не null в качестве упорядочения, id в противном случае:

Поскольку вы хотите rank_index , чтобы он был впереди an id , -0.5 производится корректировка:

 SELECT *
FROM table
ORDER BY IF(rank_index IS NULL, id, rank_index - 0.5)
  

Комментарии:

1. И что произойдет, если я захочу заказать его по умолчанию не по идентификатору, а что-то вроде a performance_index , что означает, насколько «понравился» этот продукт. Просто измените свой SQL-запрос и используйте performance_index вместо id ? Потому что для меня это звучит так, как будто это работает только с id id увеличивающимся значением, performance_index не будет.

2. order by может быть любым полем в запросе или производным от него выражением. Это не зависит от id того, что это что-то другое, кроме чего-то, с чем можно сортировать и сравнивать rank_index - 0.5 (в данном случае число).

3. Но теперь возникает проблема… Я хочу, чтобы новейший продукт всегда был на вершине. Итак, упорядочил по id убыванию… Но это приводит к проблеме, заключающейся в том, что, когда я даю rank_index 2, продукт является предпоследним продуктом… Есть идеи о том, как упорядочить его по убыванию, имея продукт с rank_index 2 на втором месте?

4. здесь возникает другая аналогичная проблема? rank_index 0.5 и объявление DESC до конца sql для убывания. Если вы хотите перейти к более общему, rank_index может быть двойным / плавающим, поэтому вы можете ввести 2 , 2.4 , 2.44 при условии, что он остается ниже 0,5.

5. Задайте вопрос, который полностью описывает вашу проблему в следующий раз или сейчас, в качестве нового вопроса.

Ответ №3:

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

 CREATE TABLE table1 (
    `id` INTEGER,
    `title` VARCHAR(18),
    `rank_index` INT
);

INSERT INTO table1
    (`id`, `title`, `rank_index`)
VALUES
    ('1', 'An awesome product', NULL),
    ('2', 'Another product', '5'),
    ('3', 'Baby car', NULL),
    ('4', 'Green carpet', '2'),
    ('5', 'Toy', NULL);

SELECT *
FROM table1
ORDER BY IF(rank_index IS NULL, id, rank_index   .01)
  
  ---- -------------------- ------------ 
| id | title              | rank_index |
 ---- -------------------- ------------ 
| 1  | An awesome product | NULL       |
| 4  | Green carpet       | 2          |
| 3  | Baby car           | NULL       |
| 5  | Toy                | NULL       |
| 2  | Another product    | 5          |
 ---- -------------------- ------------ 
  

db<> скрипка здесь