例如,如果列A和列B具有值:
+---+---+
| A | B |
+---+---+
| 2 | 1 |
| 5 | 1 |
| 6 | 1 |
| 1 | 2 |
| 5 | 2 |
| 0 | 2 |
| 2 | 3 |
| 7 | 3 |
| 4 | 3 |
| 5 | 4 |
+---+---+
从B的每一组中,我想从A中获得最高的数字。但是,我不想包括B中的数字较高但A值小于前一个的结果。我知道这在单词中没有意义,但这就是我想要的最终结果:
+---+---+
| A | B |
+---+---+
| 6 | 1 |
| 7 | 3 |
+---+---+
到目前为止,我有类似“选择max(a),b来自table1 group by b”的内容,但这并没有省略B更高但最大A更小的那些。我知道我可以在PHP中仔细阅读该查询的结果,并删除A值小于之前的A值的那些,但是如果可能的话我想把它全部放在mysql查询中。
答案 0 :(得分:5)
此技术将表与其自身的聚合版本连接,但是连接偏移一个,因此每一行都与前一个B的MAX(A)值相关联。然后它匹配当前A大于其中任何一个的行,如果它没有找到任何行,则它不包括该行。然后我们汇总最终选择以获得您所追求的结果。
SELECT
MAX(source_row.A) as A,
source_row.B
FROM ab as source_row
LEFT JOIN (SELECT MAX(A) as A, B FROM ab GROUP BY B) AS one_back
ON one_back.B = source_row.B-1
WHERE (one_back.A IS NULL)
OR one_back.A < source_row.A
GROUP BY B
我测试了这个: - )
我想分享一下我如何提出这些解决方案;因为我认为人们开始“集中思考”很重要......这是我读过的有关JOINS的最佳建议,你需要设想你的查询正在使用的中间“集合”。为了说明这一点,这里是中间“集合”的表示,它是该查询的关键部分;它是表格,因为它存在“加入”其自身的聚合版本。
+------+------+------------+------------+
| A | B | one_back.B | one_back.A |
+------+------+------------+------------+
| 2 | 1 | NULL | NULL |
| 5 | 1 | NULL | NULL |
| 6 | 1 | NULL | NULL |
| 1 | 2 | 1 | 6 |
| 5 | 2 | 1 | 6 |
| 0 | 2 | 1 | 6 |
| 2 | 3 | 2 | 5 |
| 7 | 3 | 2 | 5 |
| 4 | 3 | 2 | 5 |
| 5 | 4 | 3 | 7 |
+------+------+------------+------------+
然后,实际的集合在内存中创建(完整的连接版本永远不会完全在内存中,因为MySQL一知道它们就不会消除行“切割”:
+------+------+------------+------------+
| A | B | one_back.B | one_back.A |
+------+------+------------+------------+
| 2 | 1 | NULL | NULL |
| 5 | 1 | NULL | NULL |
| 6 | 1 | NULL | NULL |
| 7 | 3 | 2 | 5 |
+------+------+------------+------------+
然后,当然,它会将结果汇总到最终形式,只从原始行中选择A和B.
答案 1 :(得分:1)
更简单的解决方案是使用变量存储前一行的a
值,并在每次迭代时进行比较。这也解释了b
列中可能存在间隙的情况,其中数字并非完全按顺序排列:
SELECT @val:=a.a AS a, a.b
FROM
(
SELECT MAX(a) AS a, b
FROM tbl
GROUP BY b
) a
WHERE a.a > IFNULL(@val,-1)
答案 2 :(得分:0)
Select Z.a, Z.b from
(select a, b, rank() over (order by b) as ranker from (select max(a) a, b from table1 group by b) Y) Z left join
(select a, b, rank() over (order by b) as ranker from (select max(a) a, b from table1 group by b) Y1) Z1
on Z.ranker = Z1.ranker + 1
where Z.a > isnull(Z1.a, -100000)