0

例如,如果 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 |
+---+---+

到目前为止,我有类似“select max(a), b from table1 group by b”之类的东西,但这并没有忽略 B 较高但最大 A 较小的那些。我知道我可以在 PHP 中仔细阅读该查询的结果并删除 A 值小于前一个 A 值的结果,但如果可能的话,我想将其全部放入 mysql 查询中。

4

3 回答 3

5

这种技术将表与自身的聚合版本连接起来,但连接偏移了 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。

于 2012-07-13T02:32:31.143 回答
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)
于 2012-07-13T02:48:40.550 回答
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)
于 2012-07-13T02:33:40.150 回答