简体   繁体   English

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

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

I have three tables "Users" , "Subjects" and "Marks" like 我有三个表“ Users”,“ Subjects”和“ Marks”,例如

Users Table 用户表

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

Subjects Table 科目表

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

Marks Table 标记表

u_id is the foreign key of Users (id) and s_id is foreign key of Subjects(id) 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

and I wish for the result to be like 我希望结果能像

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

Using Join 使用加入

So far I have only been able to get 到目前为止,我只能得到

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

Using the following query 使用以下查询

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; "

Well, after reading the answers, I wanted to post my own one: 好了,阅读答案后,我想发表自己的答案:

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

You can check that makes all you want in SqlFiddle: http://sqlfiddle.com/#!9/f567b/1 您可以在SqlFiddle中检查是否满足所有要求: http ://sqlfiddle.com/#!9/f567b/1

The important part is the grouping of all the elements according to the user id, and the way of writing the results from rows in a table to columns in another table. 重要的部分是根据用户标识对所有元素进行分组,以及将结果从表中的行写入另一表中的列的方式。 As written in @TheShalit answer, the way of achieving that is just assigning the value as a column. 如@TheShalit答案中所写,实现该目标的方法只是将值分配为列。 Problem is that when grouping by user, you'll have a lot of values there from where you have to select the important one (the one that is not 0 neither NULL , XD). 问题在于,按用户分组时,您将不得不从中选择很多重要的值(一个不为0的NULL ,既不是NULL ,也不是XD)。 COALESCE function makes sure that you always return a integer, just in case a NULL is given. COALESCE函数可确保您始终返回整数,以防万一给出NULL

It's also important to notice that you'll have to build the SQL with the names of the subjects and the ids from database, as SQL can't retrieve the name of the elements to write them directly as names of the columns. 同样重要的是要注意,您必须使用主题名称和数据库中的ID来构建SQL,因为SQL无法检索元素的名称以直接将它们写为列的名称。 That's why I wrote 'Chem', 'Phys' and 'Eng' instead of the right names. 这就是为什么我写“ Chem”,“ Phys”和“ Eng”而不是正确的名称的原因。 In fact, would be easier if you just wrote the id of the subject instead of a name, just to retrieve the elements later when you'll fetch the rows. 实际上,如果您只写主题的ID而不是名称,那会更容易,以便稍后在提取行时检索元素。

Take into account that is VERY IMPORTANT that you'll table will have the right indexes there. 考虑到非常重要的一点,您的表将在那里具有正确的索引。 Make sure you have an UNIQUE id on the table marks with users and subjects to avoid having more than one value there stored 请确保你有一个UNIQUE的表ID marks与用户和对象,以避免多个值存储在那里

Use select like this(with joins and group by student): 使用这样的选择(按学生加入和分组):

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

You will need to do something like: 您将需要执行以下操作:

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

You are getting 3 different values from a single table but different rows so you need to join the marks table with itself to be able to get the values from 3 different records into 1 result row 您将从单个表中获取3个不同的值,但行不同,因此您需要将marks表与自身连接,以便能够将3个不同的记录中的值获取到1个结果行中

I used the values that you defined as primary id's for your 3 subjects in your question in the where clause to make sure you are getting the correct result for each subject 我在where子句中为问题中的3个主题使用了您定义为主要ID的值,以确保您获得每个主题的正确结果

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

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