2017-08-16 92 views
2

我有3个表:的MySQL MAX()GROUP BY 3个表

CREATE TABLE IF NOT EXISTS sportsman (
    sportsman_id int NOT NULL AUTO_INCREMENT, 
    sportsman_name varchar(255) NOT NULL, 
    PRIMARY KEY (sportsman_id) 
); 

CREATE TABLE IF NOT EXISTS competition (
    competition_id int NOT NULL AUTO_INCREMENT, 
    competition_name varchar(255) NOT NULL, 
    PRIMARY KEY (competition_id) 
); 

CREATE TABLE IF NOT EXISTS results (
    competition_id int, 
    sportsman_id int, 
    result float, 
    FOREIGN KEY (sportsman_id) REFERENCES sportsman(sportsman_id), 
    FOREIGN KEY (competition_id) REFERENCES competition(competition_id) 
); 

这里是样本数据:

INSERT INTO `sportsman` (`sportsman_name`) VALUES ('sportsman1'); 
INSERT INTO `sportsman` (`sportsman_name`) VALUES ('sportsman2'); 

INSERT INTO `competition` (`competition_name`) VALUES ('competition1'); 
INSERT INTO `competition` (`competition_name`) VALUES ('competition2'); 

INSERT INTO `results` (`competition_id`, `sportsman_id`, `result`) VALUES ('1', '1', '20'); 
INSERT INTO `results` (`competition_id`, `sportsman_id`, `result`) VALUES ('1', '2', '25'); 

INSERT INTO `results` (`competition_id`, `sportsman_id`, `result`) VALUES ('2', '1', '18'); 
INSERT INTO `results` (`competition_id`, `sportsman_id`, `result`) VALUES ('2', '2', '23'); 

我需要得到competition_name,最大的结果,sportsman_name。

我的查询是:

SELECT 
    c.`competition_name`, 
    MAX(r.`result`), 
    s.`sportsman_name` 
FROM `competition` c 
INNER JOIN `results` r ON c.`competition_id` = r.`competition_id` 
INNER JOIN `sportsman` s ON s.`sportsman_id` = r.`sportsman_id` 
GROUP BY c.`competition_name`; 

它按competition_name,发现最大的结果。但它选择了第一个sportsman_name。

有什么建议吗?

+1

你想什么要发生的,而不是 – Strawberry

+0

可能的复制[取它具有最高值的列行(https://stackoverflow.com/questions/121387/fetch-该行具有最大值的列) – Uueerdo

回答

1

GROUP BY sportsman_name也可以在每场比赛中获得每个参赛者的MAX(结果)。

SELECT 
    c.`competition_name`, 
    MAX(r.`result`), 
    s.`sportsman_name` 
FROM `competition` c 
INNER JOIN `results` r ON c.`competition_id` = r.`competition_id` 
INNER JOIN `sportsman` s ON s.`sportsman_id` = r.`sportsman_id` 
GROUP BY c.`competition_name`, s.`sportsman_name`; 

Link to a live demo to try it out

如果你只想显示最高得分手的名字:

SELECT 
    c.`competition_name`, result, r.sportsman_id, sportsman_name 
FROM 
    `competition` c 
     INNER JOIN 
    `results` r ON c.`competition_id` = r.`competition_id` 
     AND r.`sportsman_id` = (SELECT 
      rs.`sportsman_id` 
     FROM 
      results rs 
     WHERE 
      rs.`competition_id` = r.`competition_id` 
     ORDER BY rs.`result` DESC 
     LIMIT 1) 
     INNER JOIN 
    `sportsman` s ON s.sportsman_id = r.sportsman_id 
GROUP BY c.`competition_name`; 

Fiddle

+0

感谢@Exomus小提琴。 – ishegg

+0

我认为OP希望运动员的名字有最大的效果。 –

+0

哦......我明白了。我已经更新了答案,以说明如何实现这一点。 – ishegg

0

在MySQL最简单的方法是使用group_concat()/substring_index()

SELECT c.`competition_name`, MAX(r.`result`), 
     SUBSTRING_INDEX(GROUP_CONCAT(s.`sportsman_name` ORDER BY r.result DESC), ',', 1) as sportspersons_name 
FROM `competition` c INNER JOIN 
    `results` r 
    ON c.`competition_id` = r.`competition_id` INNER JOIN 
    `sportsman` s 
    ON s.`sportsman_id` = r.`sportsman_id` 
GROUP BY c.`competition_name`; 

这有一定的局限性。首先,如果竞争对手的名字可以有逗号,那么你需要另一个分隔符(如'|');这是对查询的轻微调整。

其次,GROUP_CONCAT()的内部缓冲区的默认最大长度约为1,000个字符。对于您的示例数据,这不可能是一个问题。但限制是很好的知道(可以增加)。

两种替代方法解决这个问题。一个使用额外的查询来获得最大的结果,并返回“join”。第二个使用变量。在大多数数据库中,您只需使用ROW_NUMBER(),但MySQL不支持ANSI标准功能。

+0

为什么你留下GROUP_CONCAT的最后一个参数为空?查询工作正常,如果我把1作为最后一个参数。 '',','1')as sportspersons_name' –

+0

@ sta.ck。 。 。这应该是'1',没有引号。 –

+0

@ sta.ck。 。 。这个版本应该比在子查询中使用'join'和'group by'的版本更高效一些。 –

0

我的同事给我发了另一种解决我的问题。也许这将帮助别人

SELECT 
    c.competition_name, 
    r.result, 
    s.sportsman_name 
FROM competition c 
JOIN (SELECT 
    MAX(result) result, competition_id 
FROM results 
GROUP BY competition_id 
) AS temp ON temp.competition_id = c.competition_id 
JOIN results r ON r.result = temp.result AND r.competition_id = temp.competition_id 
JOIN sportsman s ON s.sportsman_id = r.sportsman_id 
WHERE temp.competition_id IS NOT NULL; 
+0

只是抬头:你只能接受一个答案。 – ishegg

+0

好的。然后,我会接受你的答案,因为1.你是来自于计算器,并且2.你的解决方案更通用。 –

+0

我不是从堆栈溢出:)只是接受最有帮助的答案。我在另一个线程上问了一个问题!如果可以,请回答。 – ishegg