带有join语句的sql中多行的总和

Posted

技术标签:

【中文标题】带有join语句的sql中多行的总和【英文标题】:Sum of multiple rows in sql with join statement 【发布时间】:2022-01-17 09:06:33 【问题描述】:

我正在尝试对同一运动员的多行求和,以便返回他们总共赢得的奖牌总数。我有以下代码:

CREATE TABLE athlete (
    athlete_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    name TINYTEXT NOT NULL,
    country TINYTEXT NOT NULL,
    birthdate DATE NOT NULL,
    age INT UNSIGNED,
    height_inch INT UNSIGNED,
    PRIMARY KEY (athlete_id)
);

INSERT INTO athlete (name, country, birthdate, age, height_inch) VALUES ('Simone Biles', 'United States', '1997-03-14', 24, 56);
INSERT INTO athlete (name, country, birthdate, age, height_inch) VALUES ('Michael Phelps', 'United States', '1985-06-30', 36, 76);

CREATE TABLE sport (
    sport_id INT UNSIGNED NOT NULL,
    sport TINYTEXT NOT NULL,
    PRIMARY KEY (sport_id)
);

INSERT INTO sport VALUES (101, 'Skiing');
INSERT INTO sport VALUES (102, 'Biathlon');
INSERT INTO sport VALUES (103, 'Curling');
INSERT INTO sport VALUES (104, 'Skating');
INSERT INTO sport VALUES (105, 'Ice Hockey');
INSERT INTO sport VALUES (106, 'Luge');
INSERT INTO sport VALUES (107, 'Snowboard');
INSERT INTO sport VALUES (108, 'Basketball');
INSERT INTO sport VALUES (109, 'Gymnastics');
INSERT INTO sport VALUES (110, 'Swimming');
INSERT INTO sport VALUES (111, 'Diving');
INSERT INTO sport VALUES (112, 'Track and Field');
INSERT INTO sport VALUES (113, 'Badminton');
INSERT INTO sport VALUES (114, 'Tennis');
INSERT INTO sport VALUES (115, 'Volleyball');
INSERT INTO sport VALUES (116, 'Skateboard');
INSERT INTO sport VALUES (117, 'Soccer');
INSERT INTO sport VALUES (118, 'Golf');
INSERT INTO sport VALUES (119, 'Cycling');
INSERT INTO sport VALUES (120, 'Climbing');
INSERT INTO sport VALUES (121, 'Surfing');
INSERT INTO sport VALUES (122, 'Water Polo');
INSERT INTO sport VALUES (123, 'Karate');


CREATE TABLE olympics (
    olympics_id INT UNSIGNED NOT NULL,
    season TINYTEXT NOT NULL,
    year YEAR NOT NULL,
    city TINYTEXT NOT NULL,
    PRIMARY KEY (olympics_id)
);  

INSERT INTO olympics VALUES (1001, 'Summer', 1936, 'Berlin');
INSERT INTO olympics VALUES (1002, 'Summer', 1956, 'Melbourne');
INSERT INTO olympics VALUES (1003, 'Summer', 1960, 'Rome');
INSERT INTO olympics VALUES (1004, 'Summer', 1964, 'Tokyo');
INSERT INTO olympics VALUES (1005, 'Summer', 1976, 'Montreal');
INSERT INTO olympics VALUES (1006, 'Summer', 1984, 'Los Angelos');
INSERT INTO olympics VALUES (1007, 'Summer', 1996, 'Atlanta');
INSERT INTO olympics VALUES (1008, 'Summer', 2000, 'Sydney');
INSERT INTO olympics VALUES (1009, 'Summer', 2004, 'Athens');
INSERT INTO olympics VALUES (1010, 'Summer', 2008, 'Beijing');
INSERT INTO olympics VALUES (1011, 'Summer', 2012, 'London');
INSERT INTO olympics VALUES (1012, 'Summer', 2016, 'Rio de Janeiro');
INSERT INTO olympics VALUES (1013, 'Summer', 2020, 'Tokyo');

CREATE TABLE sport_events (
    sport_id INT UNSIGNED NOT NULL, 
    event_id INT UNSIGNED NOT NULL,
    event TINYTEXT NOT NULL,
    PRIMARY KEY (event_id),
    FOREIGN KEY (sport_id) REFERENCES sport (sport_id)
);

INSERT INTO sport_events VALUES (101, 501, 'Alpine Skiing');
INSERT INTO sport_events VALUES (101, 502, 'Cross-Country Skiing');
INSERT INTO sport_events VALUES (104, 503, 'Figure Skating');
INSERT INTO sport_events VALUES (101, 504, 'Freestyle Skiing');
INSERT INTO sport_events VALUES (104, 505, 'Short Track Speed Skating');
INSERT INTO sport_events VALUES (101, 506, 'Ski Jumping');
INSERT INTO sport_events VALUES (107, 507, 'Half-pipe');
INSERT INTO sport_events VALUES (101, 508, 'Half-pipe');
INSERT INTO sport_events VALUES (104, 509, 'Speed Skating');
INSERT INTO sport_events VALUES (109, 510, 'Artistic Gymnastics');
INSERT INTO sport_events VALUES (109, 511, 'Rhythmic Gymnastics');
INSERT INTO sport_events VALUES (115, 512, 'Beach Volleyball');
INSERT INTO sport_events VALUES (112, 513, 'High Jump');
INSERT INTO sport_events VALUES (112, 514, '100m');
INSERT INTO sport_events VALUES (112, 515, '200m');
INSERT INTO sport_events VALUES (112, 516, '400m');
INSERT INTO sport_events VALUES (112, 517, '800m');
INSERT INTO sport_events VALUES (112, 518, '4x100m relay');
INSERT INTO sport_events VALUES (112, 519, 'Triple Jump');

CREATE TABLE athlete_sport (
    athlete_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    sport_id INT UNSIGNED NOT NULL,
    PRIMARY KEY (athlete_id),
    FOREIGN KEY (athlete_id) REFERENCES athlete (athlete_id),
    FOREIGN KEY (sport_id) REFERENCES sport (sport_id)
);

INSERT INTO athlete_sport (sport_id) VALUES (109);
INSERT INTO athlete_sport (sport_id) VALUES (110);

CREATE TABLE compete (
    athlete_id INT UNSIGNED NOT NULL,
    olympics_id INT UNSIGNED NOT NULL,
    sport_id INT UNSIGNED NOT NULL,
    event_id INT UNSIGNED,
    gold INT UNSIGNED,
    silver INT UNSIGNED,
    bronze INT UNSIGNED,
    FOREIGN KEY (olympics_id) REFERENCES olympics (olympics_id),
    FOREIGN KEY (athlete_id) REFERENCES athlete (athlete_id),
    FOREIGN KEY (event_id) REFERENCES sport_events (event_id)   
);

INSERT INTO compete VALUES (1, 1012, 109, 510, 4, 0, 1);
INSERT INTO compete VALUES (1, 1013, 109, 510, 0, 1, 1); 
INSERT INTO compete VALUES (2, 1009, 110, NULL, 6, 0, 2);
INSERT INTO compete VALUES (2, 1010, 110, NULL, 8, 0, 0);
INSERT INTO compete VALUES (2, 1011, 110, NULL, 4, 2, 0);
INSERT INTO compete VALUES (2, 1012, 110, NULL, 5, 1, 0);

我查看了人们发布的其他答案,他们中的大多数人只是说要使用 group by,但是当我使用它时,它只是以不同的顺序将名称或奖牌数量排列在一起。我正在努力得到它,所以它说 simone bilis 的奖牌总数是 7 枚,michael phelps 是 28 枚,仅在一张桌子上。

这是我的查询,它返回他们参加过的每场奥运会的奖牌总和,但如果我再次使用 group by 它只是订购它们。

 select a.name, gold+silver+bronze as medalTotal from athlete a join compete c using (athlete_id) group by medalTotal;
+----------------+------------+
| name           | medalTotal |
+----------------+------------+
| Simone Biles   |          2 |
| Simone Biles   |          5 |
| Michael Phelps |          6 |
| Michael Phelps |          8 |
+----------------+------------+

【问题讨论】:

你应该按名字分组,而不是奖牌总数。 这将使迈克尔·菲尔普斯获得 8 枚奖牌,西蒙娜·比尔斯获得 5 枚奖牌,但它仍然不能总结一切。 您需要使用SUM() 在组中跨行添加值。 谢谢,我不确定它是否会与其中的添加一起工作,但确实可以。 【参考方案1】:

您需要执行以下操作:

按运动员分组 总结每种奖牌类型 将每种奖牌类型的总和相加

【讨论】:

【参考方案2】:

您需要按运动员分组,而不是总数。

您必须使用聚合函数来组合组中所有行的值。使用SUM() 将它们加在一起。

select a.name, SUM(b.gold+b.silver+b.bronze) as medalTotal 
from athlete a 
join compete c using (athlete_id) 
group by a.athlete_id;

【讨论】:

【参考方案3】:

您应该使用独特的东西(例如 athelet id)来应用组。

这将获得所有奖牌号码包括零奖牌的所有运动员 如果您只想获得奖牌,请仅使用加入。

select 
   a.name, sum(gold+silver+bronze) as medalTotal 
from 
   athlete a 
left join 
   compete c on c.athlete_id = a.athlete_id 
group by 
   a.athlete_id 

【讨论】:

以上是关于带有join语句的sql中多行的总和的主要内容,如果未能解决你的问题,请参考以下文章

带有 JOIN 和 WHERE 子句的 SQL 语句

带有条件 CASE 语句的 SQL LEFT JOIN

请高手解答几个sql的join的问题的疑惑。我用的是MSSqlserver。

带有 INNER JOIN 的两个表的 SQL INSERT 语句

选择总和和多行的语句

第九章 SQL查询数据库