字段为0的子订单

时间:2013-04-05 14:12:27

标签: mysql

所以我找不到这个问题的答案,我有以下问题:

SELECT *
FROM bans
WHERE
    removed = 0
AND
    (
        (`time` + `length` - UNIX_TIMESTAMP()) > 0
    OR
        length = 0
    )
ORDER BY length = 0,(`time` + `length` - UNIX_TIMESTAMP())

它会从表中获得所有禁令,并根据它们何时取消禁止来命令它们。但是长度为0的禁令是永久禁止的,它们应该在列表的底部。哪个已经有效了。但我希望这些永久禁令可以通过banid降序。目前它们没有按默认顺序升序。

如果我把asc放入其中,那么孔的顺序会被搞砸

数据库:

CREATE TABLE IF NOT EXISTS `rp_bans` (
  `banid` int(11) NOT NULL AUTO_INCREMENT,
  `steamid` text NOT NULL,
  `name` text NOT NULL,
  `adminid` text NOT NULL,
  `aname` text NOT NULL,
  `reason` text NOT NULL,
  `time` int(11) NOT NULL,
  `length` int(11) NOT NULL,
  `removed` tinyint(1) NOT NULL,
  PRIMARY KEY (`banid`)
)

示例数据:

id  time    length  current time    timeleft
1   1365410228  0       1365411228  -1000
2   1365410229  3600    1365411228  2601
3   1365410230  0       1365411228  -998
4   1365410231  84000   1365411228  83003
5   1365410232  3600    1365411228  2604
6   1365410233  0       1365411228  -995
7   1365410234  800000  1365411228  799006

预期结果:

id  time    length  current time    timeleft
2   1365410229  3600    1365411228  2601
5   1365410232  3600    1365411228  2604
4   1365410231  84000   1365411228  83003
7   1365410234  800000  1365411228  799006
6   1365410233  0       1365411228  -995
3   1365410230  0       1365411228  -998
1   1365410228  0       1365411228  -1000

因此,如果长度不为0,则按时间上升的顺序(从时间+长度 - 当前时间计算)。当length为0时,需要按id在降序长度不为0的条目后面进行排序。

3 个答案:

答案 0 :(得分:1)

你可以拆分它,UNION它们:

(SELECT * FROM rp_bans WHERE length > 0 ORDER BY id ASC LIMIT 10) 
UNION
(SELECT * FROM rp_bans WHERE length = 0 ORDER BY id DESC LIMIT 10)

你必须LIMIT他们;来自docs

  

但是,对单个SELECT语句使用ORDER BY并不意味着行在最终结果中出现的顺序,因为UNION默认生成一组无序行。因此,在此上下文中使用ORDER BY通常与LIMIT结合使用,因此它用于确定要为SELECT检索的所选行的子集,即使它不一定影响这些行的顺序。最终的UNION结果。

我发现比LIMIT更高的结果也可以。

答案 1 :(得分:1)

尝试就好了

ORDER BY IF(length=0, length DESC ,(`time` + `length` - UNIX_TIMESTAMP()) DESC ) 

编辑:

ORDER BY
CASE WHEN length=0 = 0 THEN length END DESC,
 (`time` + `length` - UNIX_TIMESTAMP())  DESC

编辑:

ORDER BY
CASE WHEN length != 0  THEN length END ASC,
CASE WHEN length =0 then time END  DESC

DEMO

答案 2 :(得分:0)

ORDER BY更改为

ORDER BY length = 0, banid DESC

请注意,由于OR子句,您的查询将始终执行全表扫描。

此查询的效果会更好:

    SELECT *
    FROM rp_bans
    WHERE
        removed = 0
    AND
        length = 0
UNION ALL
    SELECT *
    FROM rp_bans
    WHERE
        removed = 0
    AND
        length > 0 AND (time + length) > UNIX_TIMESTAMP()
ORDER BY length = 0, banid DESC

如果添加以下索引:

ALTER TABLE rp_bans ADD INDEX removed_length_time (removed, length, time);

一个工作示例位于http://sqlfiddle.com/#!2/45fa6/2/0