0

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

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,则按 timeleft 升序排列(根据时间 + 长度 - 当前时间计算)。当长度为 0 时,它需要按 id 降序排列在长度不为 0 的条目后面。

4

3 回答 3

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他们;来自文档

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

我发现取LIMIT高于结果也有效。

于 2013-04-05T14:18:19.333 回答
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

演示

于 2013-04-05T14:26:14.150 回答
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

于 2013-04-05T14:38:22.610 回答