mysql - SQL 仅选择列上具有自定义最大值的行

标签 mysql sql greatest-n-per-group

我需要一些有关 MySQL 请求的帮助,以仅选择列上具有最大值的行。

我已经阅读并实现了那里给出的解决方案: SQL Select only rows with Max Value on a Column

SELECT * FROM yourtable AS yt1
LEFT OUTER JOIN yourtable yt2 ON (yt1.id = yt2.id AND yt1.rev < yt2.rev)
WHERE yt2.id IS NULL;

它工作正常,但前提是您要过滤的字段实际上是最大值或最小值。

如果您想过滤自定义订单怎么办?

id   rev   content..
.1.  1 
.2   1......---...
.1   2......---...
.1   3......---...

也就是说,不是选择上表中的两行:[1, 3, ...][2, 1, ..],您希望你的结果集是 [1, 2, ...][2, 1, ..] 因为已经确定 rev=2 有更高的优先于 rev=3rev=1

是否需要重新定义“<”或其他内容的顺序关系?

我宁愿避免使用子选择。

谢谢。

最佳答案

示例数据:

CREATE TABLE yourtable
    (`id` int, `rev` int, content varchar(20))
;

INSERT INTO yourtable
    (`id`, `rev`, content)
VALUES
    (1, 1, 'a'),
    (2, 1, 'b'),
    (1, 2, 'c'),
    (1, 3, 'd')
;

解决方案一:

SELECT * FROM yourtable AS yt1
LEFT OUTER JOIN yourtable yt2 ON (yt1.id = yt2.id AND FIELD(yt1.rev, 1,3,2) < FIELD(yt2.rev, 1,3,2))
WHERE yt2.id IS NULL;

但我不喜欢在联接的列上使用函数,尤其是在进行范围比较而不是相等比较时。

解决方案 2:

SELECT id, rev, content FROM (
  SELECT yt.*, @grpnum := IF(id != @prevgrp, 1, @grpnum + 1) as my_filter, @prevgrp := id 
  FROM yourtable yt, 
  (SELECT @grpnum:=0, @prevgrp := 0) v 
  ORDER BY id, FIELD(rev, 1, 3, 2) DESC
) sq
WHERE my_filter = 1;

结果:

| ID | REV | CONTENT |
|----|-----|---------|
|  1 |   2 |       c |
|  2 |   1 |       b |

解释方案二:

首先,我从 yourtable 中选择所有内容,然后按 id 排序,然后按 FIELD(rev, 1, 3, 2) 排序。这个 FIELD() 函数有什么作用?

考虑这个数据:

mysql> select id from value order by id;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
|  6 |
+----+

现在,当你这样做的时候

mysql> select id, field(id, 3,2,5) from value order by id;
+----+------------------+
| id | field(id, 3,2,5) |
+----+------------------+
|  1 |                0 |
|  2 |                2 |
|  3 |                1 |
|  4 |                0 |
|  5 |                3 |
|  6 |                0 |
+----+------------------+

你看,该函数返回函数参数列表中 id 列的索引。未找到的所有内容都返回为 0

阅读更多相关信息 here in the manual .

因为我们想要最大值,所以我们翻转了 FIELD() 参数列表中的顺序。 FIELD(rev, 2, 3, 1) 我们有 FIELD(rev, 1, 3, 2) 假设优先顺序为 2最高,然后是 3,然后是 1(编辑:我现在刚刚看到,您有另一个订单,您当然也可以使用您的 CASE WHEN 构造,它的作用相同,FIELD() 功能就是少写)

下一步是在别名为 v 的子查询中动态初始化一些变量。这与在查询之前写 SET @grpnum = 0; 是一样的。

当 id 改变时(请注意,我们按 id 排序很重要,然后按 field()),我们增加另一个变量。这在外部查询中用作过滤器。

这样我们就可以返回与您在 FIELD() 函数中定义的最大值对应的所有行。

关于mysql - SQL 仅选择列上具有自定义最大值的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20491912/

相关文章:

mysql - 如果用户投票,除了计数之外还获取总计数

sql - 如何编写 SQL 查询来生成报告

mysql - SQL 获取最大日期

Mysql:修剪数字在 X 和 Y MIN/MAX 之间

mysql - 通过id输入的表单删除mysql中的行

php - MySQL/Laravel 外键约束格式不正确

Android SQL - 记事本教程

mysql - SQL 在 select 或 where 子句中插入查询

mysql - 选择有限制的唯一

sql - 如何在一个查询中最大化(日期)和使用 sql server 中的 in 功能?