如何根据两个字段的最大值select记录?
How to select records based on the max value of two fields?
给出以下简单的 table:
+-----+-------------+---------+----+
| id_ | match_op_id | version | p1 |
+-----+-------------+---------+----+
| 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 5 |
| 3 | 1 | 2 | 3 |
| 4 | 1 | 2 | 4 |
| 5 | 2 | 1 | 1 |
| 6 | 2 | 1 | 5 |
| 7 | 2 | 2 | 3 |
| 8 | 2 | 2 | 4 |
| 9 | 2 | 2 | 4 |
+-----+-------------+---------+----+
我想构建一个查询,其中 select 为每个 match_op_id
的单个记录(无论是哪个记录)提供 match_op_id
和 p1
字段从最大值 version
到最大值 p1
。所以从上面我会得到输出:
+-------------+----+
| match_op_id | p1 |
+-------------+----+
| 1 | 4 |
| 2 | 4 |
+-------------+----+
在 SO 上的一些帖子之后,我构建了一个查询,该查询 selects 所有 p1
字段为最大值的记录:
SELECT
odds_op.match_op_id, odds_op.p1
FROM
odds_op,
(SELECT
match_op_id, MAX(p1) AS p1
FROM
odds_op
GROUP BY match_op_id) AS max_p1
WHERE
odds_op.match_op_id = max_p1.match_op_id
AND odds_op.p1 = max_p1.p1
我现在不知道如何确保我只从最大值 version
中 select 最大值 p1
。我认为这可能是一个嵌套的子查询,但我无法弄清楚。我也知道我将 运行 解决一些分组问题,这样我就不会在每个 match_op_id
中得到多个记录。任何帮助将不胜感激。
对于 MySql 8.0+,您可以使用 FIRST_VALUE()
window 函数:
SELECT DISTINCT match_op_id,
FIRST_VALUE(p1) OVER (PARTITION BY match_op_id ORDER BY version DESC, p1 DESC) p1
FROM odds_op
之前的版本,使用NOT EXISTS
过滤table,这样只返回每个match_op_id
最大version
的行,然后聚合得到最大值 p1
:
SELECT o1.match_op_id, MAX(o1.p1) p1
FROM odds_op o1
WHERE NOT EXISTS (
SELECT 1
FROM odds_op o2
WHERE o2.match_op_id = o1.match_op_id AND o2.version > o1.version
)
GROUP BY o1.match_op_id
或在 WHERE
子句中使用相关子查询:
SELECT o1.match_op_id, MAX(o1.p1) p1
FROM odds_op o1
WHERE o1.version = (SELECT MAX(o2.version) FROM odds_op o2 WHERE o2.match_op_id = o1.match_op_id)
GROUP BY o1.match_op_id
参见demo。
结果:
match_op_id
p1
1
4
2
4
您可以使用 GROUP_CONCAT
允许排序的聚合函数并获取创建的字符串的第一个元素:
SELECT match_op_id,
SUBSTRING_INDEX(GROUP_CONCAT(p1 ORDER BY version DESC, p1 DESC SEPARATOR '~'),'~',1) AS p1
FROM odds_op
GROUP BY match_op_id;
输出(添加 GROUP_CONCAT 作为单独的调试列):
+--------------+-----+-----------+
| match_op_id | p1 | debug |
+--------------+-----+-----------+
| 1 | 4 | 4~3~5~1 |
| 2 | 4 | 4~4~3~5~1 |
+--------------+-----+-----------+
如果您使用的是 MariaDB,这会更简单 using LIMIT clause。
SELECT match_op_id,
GROUP_CONCAT(p1 ORDER BY version DESC, p1 DESC LIMIT 1) AS p1
FROM odds_op
GROUP BY match_op_id;
我不完全确定你想要的结果。
你说:“我现在不知道如何确保我只 select 最大版本的最大 p1。”
这是一个方法:
SELECT MAX(p1)
FROM odds_op
WHERE version = (SELECT MAX(version) FROM odds_op);
如果你想要 select match_op_id 和 p1 对 where version 是 max version,然后 p1 是 max p1(max p1 where version 是 max version),然后检查这个查询:
SELECT DISTINCT match_op_id, p1
FROM odds_op
WHERE version = (SELECT MAX(version) FROM odds_op)
AND p1 = (SELECT MAX(p1)
FROM odds_op
WHERE version = (SELECT MAX(version) FROM odds_op));
使用此值尝试不同的响应并检查结果:
INSERT INTO odds_op (id_, match_op_id, version, p1) VALUES
('1', '1', '1', '1'),
('2', '1', '1', '5'),
('3', '1', '2', '3'),
('4', '1', '2', '4'),
('5', '2', '1', '1'),
('6', '2', '1', '5');
对于我的示例数据,我的查询 return(它没有 return 对:2,5):
match_op_id
p1
1
4
对于您的示例数据,结果与您想要的相同。
这有点作弊,你必须确定你知道 p1 值的上限:
SELECT match_op_id, MAX(10*version+p1)-MAX(10*version) AS p1
FROM odds_op
GROUP BY match_op_id
这适用于小于等于 9 的 p1
。您需要在查询中的两个 10
中为最大 p1
[= 中的每个数字添加一个零14=]
此脚本正在 mysql 上运行。希望这对你也有效。编码愉快!
SELECT o1.match_op_id, MAX(o1.p1) AS p1
FROM odds_op o1
INNER JOIN (
SELECT match_op_id, MAX(version) AS version
FROM odds_op
GROUP BY match_op_id
) AS o2 ON o1.match_op_id = o2.match_op_id AND o1.version = o2.version
GROUP BY o1.match_op_id
给出以下简单的 table:
+-----+-------------+---------+----+
| id_ | match_op_id | version | p1 |
+-----+-------------+---------+----+
| 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 5 |
| 3 | 1 | 2 | 3 |
| 4 | 1 | 2 | 4 |
| 5 | 2 | 1 | 1 |
| 6 | 2 | 1 | 5 |
| 7 | 2 | 2 | 3 |
| 8 | 2 | 2 | 4 |
| 9 | 2 | 2 | 4 |
+-----+-------------+---------+----+
我想构建一个查询,其中 select 为每个 match_op_id
的单个记录(无论是哪个记录)提供 match_op_id
和 p1
字段从最大值 version
到最大值 p1
。所以从上面我会得到输出:
+-------------+----+
| match_op_id | p1 |
+-------------+----+
| 1 | 4 |
| 2 | 4 |
+-------------+----+
在 SO 上的一些帖子之后,我构建了一个查询,该查询 selects 所有 p1
字段为最大值的记录:
SELECT
odds_op.match_op_id, odds_op.p1
FROM
odds_op,
(SELECT
match_op_id, MAX(p1) AS p1
FROM
odds_op
GROUP BY match_op_id) AS max_p1
WHERE
odds_op.match_op_id = max_p1.match_op_id
AND odds_op.p1 = max_p1.p1
我现在不知道如何确保我只从最大值 version
中 select 最大值 p1
。我认为这可能是一个嵌套的子查询,但我无法弄清楚。我也知道我将 运行 解决一些分组问题,这样我就不会在每个 match_op_id
中得到多个记录。任何帮助将不胜感激。
对于 MySql 8.0+,您可以使用 FIRST_VALUE()
window 函数:
SELECT DISTINCT match_op_id,
FIRST_VALUE(p1) OVER (PARTITION BY match_op_id ORDER BY version DESC, p1 DESC) p1
FROM odds_op
之前的版本,使用NOT EXISTS
过滤table,这样只返回每个match_op_id
最大version
的行,然后聚合得到最大值 p1
:
SELECT o1.match_op_id, MAX(o1.p1) p1
FROM odds_op o1
WHERE NOT EXISTS (
SELECT 1
FROM odds_op o2
WHERE o2.match_op_id = o1.match_op_id AND o2.version > o1.version
)
GROUP BY o1.match_op_id
或在 WHERE
子句中使用相关子查询:
SELECT o1.match_op_id, MAX(o1.p1) p1
FROM odds_op o1
WHERE o1.version = (SELECT MAX(o2.version) FROM odds_op o2 WHERE o2.match_op_id = o1.match_op_id)
GROUP BY o1.match_op_id
参见demo。
结果:
match_op_id p1 1 4 2 4
您可以使用 GROUP_CONCAT
允许排序的聚合函数并获取创建的字符串的第一个元素:
SELECT match_op_id,
SUBSTRING_INDEX(GROUP_CONCAT(p1 ORDER BY version DESC, p1 DESC SEPARATOR '~'),'~',1) AS p1
FROM odds_op
GROUP BY match_op_id;
输出(添加 GROUP_CONCAT 作为单独的调试列):
+--------------+-----+-----------+
| match_op_id | p1 | debug |
+--------------+-----+-----------+
| 1 | 4 | 4~3~5~1 |
| 2 | 4 | 4~4~3~5~1 |
+--------------+-----+-----------+
如果您使用的是 MariaDB,这会更简单 using LIMIT clause。
SELECT match_op_id,
GROUP_CONCAT(p1 ORDER BY version DESC, p1 DESC LIMIT 1) AS p1
FROM odds_op
GROUP BY match_op_id;
我不完全确定你想要的结果。
你说:“我现在不知道如何确保我只 select 最大版本的最大 p1。”
这是一个方法:
SELECT MAX(p1)
FROM odds_op
WHERE version = (SELECT MAX(version) FROM odds_op);
如果你想要 select match_op_id 和 p1 对 where version 是 max version,然后 p1 是 max p1(max p1 where version 是 max version),然后检查这个查询:
SELECT DISTINCT match_op_id, p1
FROM odds_op
WHERE version = (SELECT MAX(version) FROM odds_op)
AND p1 = (SELECT MAX(p1)
FROM odds_op
WHERE version = (SELECT MAX(version) FROM odds_op));
使用此值尝试不同的响应并检查结果:
INSERT INTO odds_op (id_, match_op_id, version, p1) VALUES
('1', '1', '1', '1'),
('2', '1', '1', '5'),
('3', '1', '2', '3'),
('4', '1', '2', '4'),
('5', '2', '1', '1'),
('6', '2', '1', '5');
对于我的示例数据,我的查询 return(它没有 return 对:2,5):
match_op_id | p1 |
---|---|
1 | 4 |
对于您的示例数据,结果与您想要的相同。
这有点作弊,你必须确定你知道 p1 值的上限:
SELECT match_op_id, MAX(10*version+p1)-MAX(10*version) AS p1
FROM odds_op
GROUP BY match_op_id
这适用于小于等于 9 的 p1
。您需要在查询中的两个 10
中为最大 p1
[= 中的每个数字添加一个零14=]
此脚本正在 mysql 上运行。希望这对你也有效。编码愉快!
SELECT o1.match_op_id, MAX(o1.p1) AS p1
FROM odds_op o1
INNER JOIN (
SELECT match_op_id, MAX(version) AS version
FROM odds_op
GROUP BY match_op_id
) AS o2 ON o1.match_op_id = o2.match_op_id AND o1.version = o2.version
GROUP BY o1.match_op_id