编辑: 删除了大数字 init,并在 ifnull 测试中编辑了计数器,因此它适用于纯 MySQL:ifnull(@prec,counter) 而不是 ifnull(@prec,999999)。
如果您的起始表是 t1 并且基本请求是:
select id,counter from t1 order by id;
然后使用 mysql 变量 你可以完成这项工作:
SET @prec=NULL;
select * from (
select id,counter,@prec:= if(
ifnull(@prec,counter)>=counter,
counter,
-1) as prec
from t1 order by id
) t2 where prec<>-1;
除了 这里我需要 99999 作为列的最大值,并且可能有一种方法可以在第一个请求中将 @prec 的初始化设置为 NULL。
这里的 prec 列包含第 1 行值计数器,如果每行的计数器值小于前一行的值,则为每行的计数器值,如果为 false,则为 -1。
更新
如果在WHERE子句中完成变量赋值,则可以完全去掉外层选择:
SELECT @prec := NULL;
SELECT
id,
counter
FROM t1
WHERE
(@prec := IF(
IFNULL(@prec, counter) >= counter,
counter,
-1
)) IS NOT NULL
AND @prec <> -1
ORDER BY id;
regilero 编辑:
我可以通过这种方式使用 1 行的临时表(左连接)删除第一个初始化查询:但这可能会减慢查询速度。
(...)
FROM t1
LEFT JOIN (select @prec:=NULL as nullinit limit 1) as tmp1 ON tmp1.nullinit is null
(..)
正如@Mike 所说,使用简单的 UNION 查询甚至:
(...)
FROM t1 , (select @prec:=NULL) tmp1
(...)
如果你想避免第一个查询更好。
所以最后最好的解决方案是:
SELECT NULL AS id, NULL AS counter FROM dual WHERE (@prec := NULL)
UNION
SELECT id, counter
FROM t1
WHERE (
@prec := IF(
IFNULL(@prec, counter) >= counter,
counter,
-1 )) IS NOT NULL
AND @prec <> -1
ORDER BY id;
+--------+---------+
| id | counter |
+--------+---------+
| 353215 | 20 |
| 523532 | 10 |
| 535325 | 15 |
+--------+---------+
EXPLAIN SELECT 输出:
+----+--------------+------------+------+---------------+------+---------+------+------+------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+------+---------------+------+---------+------+------+------------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE |
| 2 | UNION | t1 | ALL | NULL | NULL | NULL | NULL | 6 | Using where |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | Using filesort |
+----+--------------+------------+------+---------------+------+---------+------+------+------------------+