Столбец обновления Mysql с порядком подзапроса по

#mysql

#mysql

Вопрос:

У меня есть таблица biblek2 items с этими 4 столбцами :

 id (autoincrement)  
catid(int)  
introtext(varchar)  
ordering(int)
  

Таблица biblek2_items

 ╔════╦═══════╦═══════════╦══════════╗
║ ID ║ catid ║ introtext ║ ordering ║
╠════╬═══════╬═══════════╬══════════╣
║  13024 ║   orange  ║  122     ║
║  22024 ║   zebra   ║  45      ║
║  33010 ║   juice   ║  55      ║
║  43002 ║   build   ║  17      ║
║  52003 ║   car     ║  87      ║
║  61610 ║   other   ║  1521    ║
║  71620 ║   other   ║  200     ║
╚════╩═══════╩═══════════╩══════════╝
  

Я ожидаю, что

Таблица biblek2_items

 ╔════╦═══════╦═══════════╦══════════╗    
║ ID ║ catid ║ introtext ║ ordering ║
╠════╬═══════╬═══════════╬══════════╣
║  52003 ║   car     ║  1       ║
║  43002 ║   build   ║  2       ║
║  33010 ║   juice   ║  3       ║
║  13024 ║   orange  ║  4       ║
║  22024 ║   zebra   ║  5       ║
╚════╩═══════╩═══════════╩══════════╝
  

Я хочу

  1. select * from biblek2_items where catid between 2001 and 3024
  2. ORDER BY introtext ASC
  3. очистите столбец ordering
  4. измените порядок столбца ordering с шагом от 1 до n в соответствии с результатом столбца order

Я пробовал это без успеха

 DECLARE @variable int    
SET @variable = 0    
UPDATE `biblek2_items`    
SET @variable = ordering = @variable   1     
WHERE ordering IN (SELECT ordering     
                 FROM `biblek2_items`    
                 WHERE catid BETWEEN 2001 AND 3024    
                 ORDER BY `introtext` DESC)
  

Я прочитал на форуме, что MySQL не может разрешить подзапросы с ORDER BY, так что не могли бы вы мне помочь

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

1. порядок BY в подзапросе в любом случае не имеет смысла, потому что вы не ОГРАНИЧИВАЕТЕ. Таким образом, будут возвращены все строки, и не имеет значения, как они упорядочены, потому что все они учитываются с помощью IN в вашем основном запросе.

2. Похоже, вы перепутали порядок car и build в своих результатах. Какую версию MySQL вы используете?

Ответ №1:

Как объяснено в комментариях : ORDER BY В вашем подзапросе все равно нет смысла, потому что вы этого не делаете LIMIT . Таким образом, будут возвращены все строки, и не имеет значения, как они упорядочены, потому что все они учитываются с IN в вашем основном запросе.

Но есть другие проблемы с вашим запросом.

Сделайте это вместо :

 SET @row_number = 0 ;

UPDATE biblek2_items, 
    (select id, catid,introtext,ordering,  (@row_number:=@row_number   1)  AS newordering 
    from biblek2_items 
    where catid between 2001 and 3024
    ORDER BY introtext ASC          
    ) as temp
SET biblek2_items.ordering =  temp.newordering
WHERE biblek2_items.ID = temp.ID
  

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

 CREATE TABLE biblek2_items_TEMP (ID INT, ordering INT);

SET @row_number = 0 ;

INSERT INTO biblek2_items_TEMP 
select id,  (@row_number:=@row_number   1)  AS newordering 
from biblek2_items 
where catid between 2001 and 3024
ORDER BY introtext ASC  
;

UPDATE biblek2_items, biblek2_items_TEMP
SET biblek2_items.ordering =  biblek2_items_TEMP.ordering
WHERE biblek2_items.ID = biblek2_items_TEMP.ID;

DROP TABLE biblek2_items_TEMP;
  

Успешно протестировано на MySQL 5.7 и MariaDB 10

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

1. Привет, мой друг, большое тебе спасибо, результат идеальный, я сохраню твой метод с временной таблицей, очень полезный

2. @JacquesAbada круто! теперь, если это отвечает на вопрос, вы должны выполнить свои обязанности по SO и пометить его как отвеченный (и когда вы найдете ответ действительно полезным, вы также можете добавить 1 😉