我想要一些关于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=3
和rev=1
。
您是否需要在“&lt;”或其他内容上重新定义订单关系?
我宁愿避免使用子选择。
感谢。
答案 0 :(得分:0)
示例数据:
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')
;
解决方案1:
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 |
解释解决方案2:
首先,我从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()
函数只是写的少了)< / em>的
下一步是在使用v
别名的子查询中动态初始化一些变量。这与在查询之前编写SET @grpnum = 0;
相同。
当ID发生变化时(请注意,我们按id
排序很重要,然后按field()
),我们会增加另一个变量。这在外部查询中用作过滤器。
这样我们就会返回FIELD()
函数中与您定义的最大值对应的所有行。
答案 1 :(得分:0)
也许是这样的,在子查询中指定优先级(你可以建立)
SELECT *
FROM yourtable AS yt1
LEFT OUTER JOIN (SELECT 1 AS rev, 9 AS rev_priority UNION SELECT 2, 9 UNION SELECT 3, 9) yt1_priority ON yt1.rev = yt1_priority.rev
LEFT OUTER JOIN yourtable yt2
ON yt1.id = yt2.id
LEFT OUTER JOIN (SELECT 1 AS rev, 9 AS rev_priority UNION SELECT 2, 9 UNION SELECT 3, 9) yt1_priority ON yt1.rev = yt2_priority.rev
ON yt1_priority.rev_priority < yt2_priority.rev_priority
WHERE yt2.id IS NULL;
(未经测试)