我想从mysql表中为每个成员选择最佳结果。 (如果有相同值的条目,则应采用事件开始日期最短的条目)
的DDL:
CREATE TABLE `results` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`discipline` int(11) NOT NULL,
`member` int(11) DEFAULT '0',
`event` int(11) DEFAULT '0',
`value` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `member_2` (`member`,`discipline`,`event`)
);
INSERT INTO results VALUES
(1,1,2,4,10),
(2,1,1,4, 8),
(3,1,2,5, 9),
(4,2,3,5, 9),
(5,1,2,6,11),
(6,1,2,7,11),
(7,1,2,1,11),
(8,1,2,3, 7);
CREATE TABLE `events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`startDate` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO events VALUES
(1 ,'Not in scope','2012-05-23'),
(3 ,'Test 0', '2014-05-09'),
(4 ,'Test 1', '2014-05-10'),
(5 ,'Test 2', '2014-05-11'),
(6 ,'Test 3', '2014-05-12'),
(7 ,'Test 4', '2014-05-13');
SELECT * FROM results;
+----+------------+--------+-------+-------+
| id | discipline | member | event | value |
+----+------------+--------+-------+-------+
| 1 | 1 | 2 | 4 | 10 |
| 2 | 1 | 1 | 4 | 8 |
| 3 | 1 | 2 | 5 | 9 |
| 4 | 2 | 3 | 5 | 9 |
| 5 | 1 | 2 | 6 | 11 |
| 6 | 1 | 2 | 7 | 11 |
| 7 | 1 | 2 | 1 | 11 |
| 8 | 1 | 2 | 3 | 7 |
+----+------------+--------+-------+-------+
SELECT * FROM events;
+----+--------------+---------------------+
| id | name | startDate |
+----+--------------+---------------------+
| 1 | Not in scope | 2012-05-23 00:00:00 |
| 3 | Test 0 | 2014-05-09 00:00:00 |
| 4 | Test 1 | 2014-05-10 00:00:00 |
| 5 | Test 2 | 2014-05-11 00:00:00 |
| 6 | Test 3 | 2014-05-12 00:00:00 |
| 7 | Test 4 | 2014-05-13 00:00:00 |
+----+--------------+---------------------+
结果应该是:
+---------+------------+--------+-------+-------+
| id | discipline | member | event | value |
+---------+------------+--------+-------+-------+
| 3 | 1 | 1 | 4 | 8 |
| 5 | 1 | 2 | 6 | 11 |
+---------+------------+--------+-------+-------+
我的第一种方法是按成员ID进行分组,但这并不容易。所以我尝试了很多来自网络和我的同事的不同方法。
最后一个是:
select res.*
from `results` as res
join (select id, max(value)
from results
join events on results.event = events.id
where discipline = 1
events.name like 'Test%'
Group by id
Order by events.startDate ASC) as tmpRes
on res.id = tmpRes.id
group by member
order by value DESC
但是此示例中的结果将是成员2的随机结果ID。
答案 0 :(得分:1)
现在应该是正确的,但如果有错误,请告诉我......
SELECT r.*
FROM events e
JOIN results r
ON r.event = e.id
JOIN
( SELECT r.member
, MIN(e.startdate) min_startdate
FROM events e
JOIN results r
ON r.event = e.id
JOIN
( SELECT member
, MAX(value) max_value
, discipline
FROM events e
JOIN results r
ON r.event = e.id
WHERE discipline = 1
AND name LIKE 'Test%'
GROUP
BY member
) x
ON x.member = r.member
AND x.max_value = r.value
AND x.discipline = r.discipline
AND e.name LIKE 'Test%'
GROUP
BY member
) y
ON y.member = r.member
AND y.min_startdate = e.startdate;
虽然速度很快,但由于这些查询可能会变得相当复杂和繁琐,因此未经证实的黑客攻击会获得相同的结果。它是这样的......
SELECT *
FROM
( SELECT r.*
FROM events e
JOIN results r
ON r.event = e.id
WHERE discipline = 1
AND name LIKE 'Test%'
ORDER
BY member
, value DESC
, startdate
) x
GROUP
BY member;
答案 1 :(得分:0)
如果我正确理解您的问题,您需要在子查询中对成员进行分组。请尝试以下方法:
select res.*
from `results` as res
join (select member, min(event) AS minEvent, max(value) AS maxValue
from results
where discipline = 1
Group by member) as tmpRes
on res.member = tmpRes.member AND res.event=tmpRes.minEvent AND res.value=tmpRes.maxValue
order by res.value
编辑(最近的评论):如果是这样的话,你需要加入事件表。除非startDate字段实际上是一个时间字段,否则它将是一个很大的混乱。
原始问题中包含所有要求会使事情变得更容易。