从具有不同行数的表中选择

时间:2016-11-17 11:32:54

标签: mysql select join union

我希望有一个简单的答案。参赛者参加一系列3场比赛。有些竞争对手只参加一场比赛。我怎样才能为所有竞争对手展示最终结果?

第1场比赛

+------+--------+
| name | result |
+------+--------+
| Ali  |     30 |
| Bob  |     28 |
| Cal  |     26 |
+------+--------+

第2场比赛

+------+--------+
| name | result |
+------+--------+
| Ali  |     32 |
| Bob  |     31 |
| Dan  |     24 |
+------+--------+

第3场比赛

+------+--------+
| name | result |
+------+--------+
| Eva  |     23 |
| Dan  |     25 |
+------+--------+

最终结果应如下所示:

+------+--------+--------+--------+
| name | result | result | result |
+------+--------+--------+--------+
| Ali  |     30 |     32 |        |
| Bob  |     28 |     31 |        |
| Cal  |     26 |        |        |
| Dan  |        |     24 |     25 |
| Eva  |        |        |     23 |
+------+--------+--------+--------+

我遇到的问题是从多个表中按名称排序。

以下是示例数据:

CREATE TABLE race (name varchar(20), result int);
CREATE TABLE race1 LIKE race;
INSERT INTO race1 VALUES ('Ali', '30'), ('Bob', '28'), ('Cal', '26');
CREATE TABLE race2 like race;
insert INTO race2 VALUES ('Ali', '32'), ('Bob', '31'), ('Dan', '24');
CREATE TABLE race3 LIKE race;
INSERT INTO race3 VALUES ('Eva', '23'), ('Dan', '25');

非常感谢!

2 个答案:

答案 0 :(得分:5)

我们走了!!!

select race1.name as name, race1.result, race2.result, race3.result from race1
    left join race2 on race2.name = race1.name 
    left join race3 on race3.name = race1.name

union

select race2.name as name, race1.result, race2.result, race3.result from race2
    left join race1 on race1.name = race2.name
    left join race3 on race3.name = race2.name

union

select race3.name as name, race1.result, race2.result, race3.result from race3
    left join race1 on race1.name = race3.name
    left join race2 on race2.name = race3.name;

它正在工作:)

答案 1 :(得分:0)

我个人会以不同的方式创建架构。 一个用户表,一个用于比赛,一个用于连接两者:

-- Create syntax for TABLE 'races'
CREATE TABLE `races` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Create syntax for TABLE 'users'
CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Create syntax for TABLE 'race_results'
CREATE TABLE `race_results` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `race_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `result` int(11) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

让我们插入一些数据(应该等于你的数据集)。

-- Insert data
INSERT INTO users (name)values('Ali'),('Bob'),('Cal'),('Dan'), ('Eva');
INSERT INTO races (name)values('Race1'),('Race2'),('Race3');
INSERT INTO race_results (user_id, race_id, result)values(1,1,30),(2,1,30),(1,2,28),(2,2,31),(3,1,26),(4,2,24),(4,3,25),(5,3,23);

然后你可以像这样编写查询:

-- Static version
SELECT us.name, sum(if(ra.name='Race1', result, null)) as Race1, sum(if(ra.name='Race2', result, null)) as Race2, sum(if(ra.name='Race3', result, null)) as Race3
FROM race_results as rr
LEFT JOIN users  as us on us.id = rr.user_id
LEFT JOIN races as ra on ra.id = rr.race_id
GROUP BY us.id;

它可以为您提供所需的结果。 (我更改了列名,使其更明显哪个结果属于哪个种族。)

但是我承认这适用于3场比赛,但如果你有30场或更多比赛怎么办?

以上是上述查询的更动态版本,它创建了自己的类型;)

-- Dynamic version
SET @sql = '';
SELECT
    @sql := CONCAT(@sql,if(@sql='','',', '),temp.output)
FROM
    (SELECT
        CONCAT("sum(if(ra.name='", race.name, "', result, null)) as ", race.name) as output
    FROM races as race
) as temp;

SET @sql = CONCAT("SELECT us.name,", @sql, " FROM race_results as rr LEFT JOIN users  as us on us.id = rr.user_id LEFT JOIN races as ra on ra.id = rr.race_id GROUP BY 1;");
SELECT @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;