この手法は、それ自体の集約バージョンに対してテーブルを結合しますが、結合は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に関して私が今まで読んだ中で最高のアドバイスであり、クエリが機能する中間の「セット」を想像する必要があります。これを説明するために、このクエリの重要な部分である中間の「セット」の表現を次に示します。それは、それ自体の集約バージョンに1つずつ「結合」されて存在するテーブルです。
+------+------+------------+------------+
| 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のみを選択して、そこからの結果を最終的な形式に集約します。