从表中选择每个成员的最大值

时间:2014-05-12 19:10:21

标签: mysql sql

我想从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。

2 个答案:

答案 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字段实际上是一个时间字段,否则它将是一个很大的混乱。

原始问题中包含所有要求会使事情变得更容易。