繁体   English   中英

在MySQL中使用自我连接进行多次连接,并按行值拆分列中的行

[英]Multiple join with self join in MySQL and split rows in columns by a row value

我有三个表“ Users”,“ Subjects”和“ Marks”,例如

用户表

id  name
1   A
2   B
3   C
4   D
5   E
6   A
7   B

科目表

id  name
1   Chemistry
2   Physics
3   English
4   Maths
5   History

标记表

u_id是用户(id)的外键,而s_id是Subjects(id)的外键

id  u_id    s_id    marks
 1     1       1     60
 2     1       2     70
 3     1       3     80
 4     2       2     80
 5     2       3     44
 6     3       1     50
 7     5       4     50
 8     4       5     50
 9     5       4    100
10     2       5    100

我希望结果能像

id  Name    Chemistry Physics English 
1   A       60        70      80
2   B       NULL      80      44
3   3       50        NULL    NULL

使用加入

到目前为止,我只能得到

name    name        marks
A       English     80
A       Physics     70
A       Chemistry   60
B       English     44
B       Physics     80
C       Chemistry   50

使用以下查询

SELECT u.name, s.name , m.marks
FROM Users as u 
RIGHT JOIN Marks as m ON m.u_id = u.id 
LEFT JOIN Subjects as s ON m.s_id = s.id  
WHERE s.name = "English" 
  OR s.name = "Physics" 
  OR s.name = "Chemistry"
ORDER BY u.name; "

好了,阅读答案后,我想发表自己的答案:

SELECT 
  u.id
, u.name

, MAX(IF(s.id = 1, COALESCE(m.mark), 0)) as 'Chem'
, MAX(IF(s.id = 2, COALESCE(m.mark), 0)) as 'Phys'
, MAX(IF(s.id = 3, COALESCE(m.mark), 0)) as 'Eng'

FROM marks m
INNER JOIN subjects s
ON s.id = m.subjects_id
INNER JOIN users u 
ON u.id = m.users_id
GROUP BY u.id

您可以在SqlFiddle中检查是否满足所有要求: http ://sqlfiddle.com/#!9/f567b/1

重要的部分是根据用户标识对所有元素进行分组,以及将结果从表中的行写入另一表中的列的方式。 如@TheShalit答案中所写,实现该目标的方法只是将值分配为列。 问题在于,按用户分组时,您将不得不从中选择很多重要的值(一个不为0的NULL ,既不是NULL ,也不是XD)。 COALESCE函数可确保您始终返回整数,以防万一给出NULL

同样重要的是要注意,您必须使用主题名称和数据库中的ID来构建SQL,因为SQL无法检索元素的名称以直接将它们写为列的名称。 这就是为什么我写“ Chem”,“ Phys”和“ Eng”而不是正确的名称的原因。 实际上,如果您只写主题的ID而不是名称,那会更容易,以便稍后在提取行时检索元素。

考虑到非常重要的一点,您的表将在那里具有正确的索引。 请确保你有一个UNIQUE的表ID marks与用户和对象,以避免多个值存储在那里

使用这样的选择(按学生加入和分组):

MAX(If(subjects.name="Chemistry",marks.marks,'')) Chemistry,
MAX(If(subjects.name="Physics",marks.marks,'')) Physics,
.....

您将需要执行以下操作:

SELECT u.NAME AS NAME,
       m_e.marks AS english,          
       m_p.marks AS physics,
       m_c.marks AS chemistry
FROM users AS u 
JOIN marks AS m_e ON m_e.u_id = u.id 
JOIN marks AS m_p ON m_p.u_id = u.id 
JOIN marks AS m_c ON m_c.u_id = u.id 
WHERE m_e.s_id = 3 AND m_c.s_id = 1 AND m_p.s_id = 2

您将从单个表中获取3个不同的值,但行不同,因此您需要将marks表与自身连接,以便能够将3个不同的记录中的值获取到1个结果行中

我在where子句中为问题中的3个主题使用了您定义为主要ID的值,以确保您获得每个主题的正确结果

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM