In a previous question I was told that if I want to store multiple languages for a user then it is best to have a separate table mapping 开发者_C百科languages and users together. That makes sense because it is a classic many-to-many relationship so that is what I have done.
My question now is what query can I write that will concatenate all the language names for each user and then display that as a table?
I made the following (is it correct?):
CREATE TABLE language (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name char(20) NOT NULL UNIQUE)
CREATE TABLE user (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name char(20) NOT NULL UNIQUE)
CREATE TABLE user_language (
id_user INT REFERENCES user(id),
id_lang INT REFERENCES language(id) )
I then inserted 3 test users, 7 test languages and inserted 9 pairs into the user_language table. Now I want to print a concatenated list of the languages each user speaks next to the users names using only one MySQL query and I have no idea how to do that. So for example I would like to see
User | Languages
--------|---------------
Bob | English, French
Alex | Spanish, Portuguese
Ivan | Russian, English, German
Any ideas? Am I even on the right track?
EDIT
I am aware of the JOIN function so printing the list out as a set of individual pairs is not my intention. I specifically want to concatenate the languages for each user without resorting to writing a loop in a script (it would be in PHP in my case). I thought there might be some way of writing a subquery and using the CONCATENATE function that might be able to help me...? Am I way off?
You'll want to take a look at using an INNER JOIN for this. Essentially, the JOIN is going to take a look at the IDs in each field and then match data together for entries that have matching IDs.
Consider the following SQL query:
SELECT user.*, language.name FROM user
INNER JOIN user_language ON user.id = user_language.id_user
INNER JOIN language ON user_language.id_lang = language.id;
Order of the INNER JOINs is important; the first thing we need to do is be able to reference language IDs relative to the user ID. The first INNER JOIN is going to give each user a list of language IDs which the user can speak. The second is going to map that language ID that was assigned to the user to a name.
However, the above will not return them in a comma-separated list. Instead, you'll get something like this:
name | language
-------------------------
bob | English
bob | Dutch
Sally | English
Sally | Spanish
Sally | German
You'll have to do some post processing to put the data into a comma-separated list. Doing so in almost any language should be fairly straightforward.
select a.name, b.name from language a, user b where id_user = b.id and id_lang = a.id;
Yes, this is a completely valid design.
SELECT user.name, language.name FROM user INNER JOIN user_language ON(user.id = user_language.id_user) INNER JOIN language ON(language.id_lang = language.id);
SELECT u.name as user, l.name as language
FROM USER u
INNER JOIN user_language ul ON u.id = ul.id_user
INNER JOIN LANGUAGE l ON ul.id_lang = l.id;
精彩评论