从0减去不在查询中工作

时间:2015-02-27 10:12:05

标签: mysql

我有这张桌子:

CREATE TABLE `page` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `sortorder` SMALLINT(5) UNSIGNED NOT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

这是我的数据:

id  sortorder
1   0
2   1

我想运行此查询:

select id from page where (sortorder = (select sortorder from page where id = 1) - 1)

(我试图找到上一页,即具有较低排序顺序的页面,如果它存在。如果不存在,我想要一个空的结果集。)

我从mysql收到的错误:

SQL Error (1690): BIGINT UNSIGNED value is out of range in '((select '0' from `page` where 1) - 1)'

更具体地说,当我跑步时:

select sortorder - 1 from page where id = 1

我明白了:

SQL Error (1690): BIGINT UNSIGNED value is out of range in '('0' - 1)'

我该怎么做才能防止这种情况发生?

2 个答案:

答案 0 :(得分:1)

尝试在' NO_UNSIGNED_SUBTRACTION'

中设置您的SQL模式
SET sql_mode =  'NO_UNSIGNED_SUBTRACTION'

答案 1 :(得分:1)

我通常使用JOIN来实现此目标,因为它们可以比子查询更好地进行优化。此查询应该产生与您相同的结果,但可能更快:

SELECT pp.*
FROM page cp             # 'cp' from 'current page'
  LEFT JOIN page pp      # 'pp' from 'previous page'
        ON pp.sortorder = cp.sortorder - 1
WHERE cp.id = 1

不幸的是,它失败了,但-1 UNSIGNED不是JOIN的错误消息。

可以通过将 ON pp.sortorder + 1 = cp.sortorder 条件写为:

来修复
-1

我将+1移到了等号的另一边,然后转向-1

您还可以使用相同的技巧修复原始查询:将+1移动到等号的另一侧;这样它变成select id from page where (sortorder + 1 = (select sortorder from page where id = 1) 并且不再有任何错误:

sortorder

现在两个查询的问题在于,由于列WHERE上没有索引,因此MySQL必须逐个检查所有行,直到找到与ON匹配的行(或{ {1}})条件,这需要花费大量时间并使用大量资源。

幸运的是,可以通过在列sortorder上添加索引来轻松修复此问题:

ALTER TABLE page ADD INDEX(sortorder);

现在可以使用两个查询。使用JOIN(和ON条件+1)的那个稍快一些。

当不满足条件时,原始查询不返回任何行。 JOIN查询返回一行NULL秒。通过将LEFT JOIN替换为INNER JOIN,可以将其修改为不返回任何行。

您可以通过从UNSIGNED列移除sortorder属性来完全绕过错误(并使用这些查询的任何版本):

ALTER TABLE page 
CHANGE COLUMN `sortorder` `sortorder` SMALLINT(5) UNSIGNED NOT NULL;