具有子请求Order By的Mysql Update列

时间:2019-03-07 12:23:29

标签: mysql

我有一个带有这4列的表格biblek2:

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

表biblek2_items

╔════╦═══════╦═══════════╦══════════╗
║ ID ║ catid ║ introtext ║ ordering ║
╠════╬═══════╬═══════════╬══════════╣
║  1 ║  3024 ║   orange  ║  122     ║
║  2 ║  2024 ║   zebra   ║  45      ║
║  3 ║  3010 ║   juice   ║  55      ║
║  4 ║  3002 ║   build   ║  17      ║
║  5 ║  2003 ║   car     ║  87      ║
║  6 ║  1610 ║   other   ║  1521    ║
║  7 ║  1620 ║   other   ║  200     ║
╚════╩═══════╩═══════════╩══════════╝

我希望

表biblek2_items

╔════╦═══════╦═══════════╦══════════╗    
║ ID ║ catid ║ introtext ║ ordering ║
╠════╬═══════╬═══════════╬══════════╣
║  5 ║  2003 ║   car     ║  1       ║
║  4 ║  3002 ║   build   ║  2       ║
║  3 ║  3010 ║   juice   ║  3       ║
║  1 ║  3024 ║   orange  ║  4       ║
║  2 ║  2024 ║   zebra   ║  5       ║
╚════╩═══════╩═══════════╩══════════╝

我想

  1. select * from biblek2_items where catid between 2001 and 3024
  2. ORDER BY introtext ASC
  3. 清空订购列
  4. 根据订单列的结果从1到n递增顺序对订单列进行重新排序

我尝试失败了

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 个答案:

答案 0 :(得分:0)

如评论中所述: 无论如何,子查询中的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上成功测试