id Subject mark Year
-------------------------
1 Maths 32 2008
1 Science 40 2009
1 Science 45 2008
1 English 50 2009
1 English 60 2008
我正在寻找这样的结果:
id Maths Science English
-----------------------------
1 32 40 & 45 50 & 60
请指教。我正在使用MySQL。
答案 0 :(得分:7)
作为@Mark suggested,GROUP_CONCAT()
可以为您提供以下结果:
SELECT id, subject, GROUP_CONCAT(mark SEPARATOR ' & ') marks
FROM results
GROUP BY id, subject;
+------+---------+---------+
| id | subject | marks |
+------+---------+---------+
| 1 | English | 50 & 60 |
| 1 | Maths | 32 |
| 1 | Science | 40 & 45 |
+------+---------+---------+
3 rows in set (0.00 sec)
从这个测试案例中:
CREATE TABLE results (id int, subject varchar(10), mark int);
INSERT INTO results VALUES (1, 'Maths', 32);
INSERT INTO results VALUES (1, 'Science', 40);
INSERT INTO results VALUES (1, 'Science', 45);
INSERT INTO results VALUES (1, 'English', 50);
INSERT INTO results VALUES (1, 'English', 60);
然而,另一种解决问题的方法是使用每个主题的子查询:
SELECT r.id,
(SELECT GROUP_CONCAT(r_eng.mark SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'English' AND r_eng.id = r.id) English,
(SELECT GROUP_CONCAT(r_eng.mark SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'Maths' AND r_eng.id = r.id) Maths,
(SELECT GROUP_CONCAT(r_eng.mark SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'Science' AND r_eng.id = r.id) Science
FROM results r
GROUP BY r.id;
将产生以下结果:
+------+---------+-------+---------+
| id | English | Maths | Science |
+------+---------+-------+---------+
| 1 | 50 & 60 | 32 | 40 & 45 |
+------+---------+-------+---------+
1 row in set (0.01 sec)
<强>更新强>
除了评论之外,您还需要考虑year
字段。幸运的是,GROUP_CONCAT()
函数采用了我们可以使用的ORDER BY
子句。让我们从一个带有年份字段的新测试用例开始:
CREATE TABLE results (id int, subject varchar(10), mark int, year int);
INSERT INTO results VALUES (1, 'Maths', 32, 2008);
INSERT INTO results VALUES (1, 'Science', 40, 2009);
INSERT INTO results VALUES (1, 'Science', 45, 2008);
INSERT INTO results VALUES (1, 'English', 50, 2009);
INSERT INTO results VALUES (1, 'English', 60, 2008);
SELECT * FROM results;
+------+---------+------+------+
| id | subject | mark | year |
+------+---------+------+------+
| 1 | Maths | 32 | 2008 |
| 1 | Science | 40 | 2009 |
| 1 | Science | 45 | 2008 |
| 1 | English | 50 | 2009 |
| 1 | English | 60 | 2008 |
+------+---------+------+------+
5 rows in set (0.00 sec)
然后我们可以将GROUP_CONCAT()
函数与ORDER BY
子句一起使用,如下所示:
SELECT id,
subject,
GROUP_CONCAT(mark ORDER BY year SEPARATOR ' & ') marks,
GROUP_CONCAT(year ORDER BY year SEPARATOR ' & ') years
FROM results
GROUP BY id, subject;
+------+---------+---------+-------------+
| id | subject | marks | years |
+------+---------+---------+-------------+
| 1 | English | 60 & 50 | 2008 & 2009 |
| 1 | Maths | 32 | 2008 |
| 1 | Science | 45 & 40 | 2008 & 2009 |
+------+---------+---------+-------------+
3 rows in set (0.00 sec)
最后,对于GROUP BY
一个水平行中的所有内容,我们可以使用前面示例中使用的子查询技术:
SELECT r.id,
(SELECT GROUP_CONCAT(r_eng.mark ORDER BY year SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'English' AND r_eng.id = r.id) English,
(SELECT GROUP_CONCAT(r_eng.year ORDER BY year SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'English' AND r_eng.id = r.id) Years_English,
(SELECT GROUP_CONCAT(r_eng.mark ORDER BY year SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'Maths' AND r_eng.id = r.id) Maths,
(SELECT GROUP_CONCAT(r_eng.year ORDER BY year SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'Maths' AND r_eng.id = r.id) Years_Maths,
(SELECT GROUP_CONCAT(r_eng.mark ORDER BY year SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'Science' AND r_eng.id = r.id) Science,
(SELECT GROUP_CONCAT(r_eng.year ORDER BY year SEPARATOR ' & ')
FROM results r_eng
WHERE r_eng.subject = 'Science' AND r_eng.id = r.id) Years_Science
FROM results r
GROUP BY r.id;
将返回以下内容:
+----+---------+---------------+-------+-------------+---------+---------------+
| id | English | Years_English | Maths | Years_Maths | Science | Years_Science |
+----+---------+---------------+-------+-------------+---------+---------------+
| 1 | 60 & 50 | 2008 & 2009 | 32 | 2008 | 45 & 40 | 2008 & 2009 |
+----+---------+---------------+-------+-------------+---------+---------------+
1 row in set (0.01 sec)
如果您希望按降序排列标记和年份,则只需在每个DESC
后添加ORDER BY year
关键字。
答案 1 :(得分:1)
第一步,看看mysql中的group_concat()功能,可能会有所帮助
SELECT `id`,
`subject`,
group_concat( `mark`
ORDER BY `year` DESC
SEPARATOR ' & '
) marks
FROM `subjects`
GROUP BY `id`,
`subject`
<强>更新强> 管理到目前为止
SELECT `id`,
IF (`subject` = 'English', `marks`, NULL) AS English,
IF (`subject` = 'Maths', `marks`, NULL) AS Maths,
IF (`subject` = 'Science', `marks`, NULL) AS Science
FROM ( SELECT `id`,
`subject`,
group_concat( `mark`
ORDER BY `year` DESC
SEPARATOR ' & '
) marks
FROM `subjects`
GROUP BY `id`,
`subject`
) x
GROUP BY `id`,
`subject`
返回
+----+---------+-------+---------+
| id | English | Maths | Science |
+----+---------+-------+---------+
| 1 | 50 & 60 | NULL | NULL |
| 1 | NULL | 32 | NULL |
| 1 | NULL | NULL | 40 & 45 |
+----+---------+-------+---------+
3 rows in set (0.01 sec)
但是不能完全获得最后一个分组权限将它全部作为一行返回。 在采用这种方法解决问题时,不知道是否有其他人可以帮助我做到最后一步....通常,我会将结果返回给PHP“按原样”,并在那里进行最后的分组;但是一个完整的MySQL解决方案会很有趣。