这种技术将表与自身的聚合版本连接起来,但连接偏移了 1,因此每一行都连接到前一个 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。