很好; 这是一种方法 - 虽然它不是最有效的......
考虑以下...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL
,dt INT NOT NULL
,PRIMARY KEY(id,dt)
);
INSERT INTO my_table VALUES
(101,1),
(101,2),
(101,3),
(101,4),
(102,1),
(102,2),
(102,3),
(102,4),
(102,5),
(103,1),
(103,2),
(103,3),
(104,1),
(104,2),
(105,1);
SELECT * FROM my_table;
+-----+----+
| id | dt |
+-----+----+
| 101 | 1 |
| 101 | 2 |
| 101 | 3 |
| 101 | 4 |
| 102 | 1 |
| 102 | 2 |
| 102 | 3 |
| 102 | 4 |
| 102 | 5 |
| 103 | 1 |
| 103 | 2 |
| 103 | 3 |
| 104 | 1 |
| 104 | 2 |
| 105 | 1 |
+-----+----+
要发现其组中每一行的位置(排名),我们可以这样做......
SELECT x.*
, COUNT(*) rank
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.dt >= x.dt
GROUP
BY x.id,x.dt
ORDER
BY id
, rank;
+-----+----+------+
| id | dt | rank |
+-----+----+------+
| 101 | 4 | 1 |
| 101 | 3 | 2 |
| 101 | 2 | 3 |
| 101 | 1 | 4 |
| 102 | 5 | 1 |
| 102 | 4 | 2 |
| 102 | 3 | 3 |
| 102 | 2 | 4 |
| 102 | 1 | 5 |
| 103 | 3 | 1 |
| 103 | 2 | 2 |
| 103 | 1 | 3 |
| 104 | 2 | 1 |
| 104 | 1 | 2 |
| 105 | 1 | 1 |
+-----+----+------+
...可以这样重写(从每个 id 中获取前 3 个)...
SELECT x.*
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.dt >= x.dt
GROUP
BY x.id
, x.dt
HAVING COUNT(*) <= 3;
+-----+----+
| id | dt |
+-----+----+
| 101 | 2 |
| 101 | 3 |
| 101 | 4 |
| 102 | 3 |
| 102 | 4 |
| 102 | 5 |
| 103 | 1 |
| 103 | 2 |
| 103 | 3 |
| 104 | 1 |
| 104 | 2 |
| 105 | 1 |
+-----+----+