为了开始,我想明确表示我不是按降序排序。
我希望通过其他方式进行排序,但是只有当第1列中第1列中的值小于其自身时,才会通过在第二列中显示内容来进一步过滤。一旦发现下一列较低,它就会停止。
示例:
Ordered by column-------------------Descending Column
353215 20
535325 15
523532 10
666464 30
473460 20
如果给出数据,我希望它只返回20,15和10.因为现在30高于10,我们不关心它下面的数据。
我到处寻找,无法找到解决方案。
答案 0 :(得分:2)
你找不到解决方案,因为这是不可能的。
SQL只在一行内工作,它不能查看它上面或下面的行。
您可以编写一个存储过程来执行此操作,实际上一次循环一行并计算逻辑。
用前端语言写它可能会更容易,无论你使用什么。
答案 1 :(得分:2)
编辑:删除了大号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列包含第一行值计数器,然后是每行的计数器值(如果它小于前一行的计数器值),并且当它变为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 |
+--------+---------+
+----+--------------+------------+------+---------------+------+---------+------+------+------------------+
| 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 |
+----+--------------+------------+------+---------------+------+---------+------+------+------------------+
答案 2 :(得分:1)
我担心你不能在SQL中做到这一点。关系数据库是为不同目的而设计的,因此没有像下一行或上一行那样的抽象。用“包装”语言在SQL之外做。
答案 3 :(得分:1)
我不确定这些是否符合您的要求,但无论如何它们可能都太慢了:
SELECT t1.col1, t1.col2
FROM tbl t1
WHERE t1.col2 = (SELECT MIN(t2.col2) FROM tbl t2 WHERE t2.col1 <= t1.col1)
或者
SELECT t1.col1, t1.col2
FROM tbl t1
INNER JOIN tbl t2 ON t2.col1 <= t1.col1
GROUP BY t1.col1, t1.col2
HAVING t1.col2 = MIN(t2.col2)
答案 4 :(得分:0)
我猜你可以将它们(按顺序)选择到一个临时表中,它也有一个自动递增列,然后从临时表中选择,根据自动递增列(id)连接到自身,但是在t1.id = t2.id + 1的情况下,然后使用where条件(和适当的顺序by和limit 1)来查找t2中下降列大于t1的行的t1.id。之后,您可以从临时表中选择id小于或等于您刚刚找到的ID。虽然不是很漂亮! :)
答案 5 :(得分:0)
实际上可能,但性能不容易优化。如果订购Col1而Col2是降序列:
首先,您创建每行与下一行的自连接(请注意,这仅在列值唯一时有效,否则您需要连接唯一值)。
(Select Col1, (Select Min(Col2) as A2 from MyTable as B Where B.A2>A.Col1) As Col1FromNextRow From MyTable As A) As D
INNER JOIN
(Select Col1 As C1,Col2 From MyTable As C On C.C1=D.Col1FromNextRow)
然后你实现“继续前进到第一个上升值”位:
Select Col2 FROM
(
(Select Col1, (Select Min(Col2) as A2 from MyTable as B Where B.A2>A.Col1) As Col1FromNextRow From MyTable As A) As D
INNER JOIN
(Select Col1 As C1,Col2 From MyTable As C On C.C1=D.Col1FromNextRow)
) As E
WHERE NOT EXISTS
(SELECT Col1 FROM MyTable As Z Where z.COL1<E.Col1 and Z.Col2 < E.Col2)
我没有测试环境,所以它可能有bug。我道歉,但希望这个想法是半清晰的。
我仍然会尝试在SQL之外执行此操作。