简体   繁体   中英

PHP and MySQL many-to-many question

Still wrapping my head around SQL and PHP, but hope someone can help with this:

I have the following tables:

1.

user table
- id
- name
- email

2.

user_group table
- user_id
- group_id

3.

group table
- id
- group_name

There is a many-to-many relationship between the user table and the group table. Now what I am trying to do build a browse users page which lists all the users in the system along with the groups that they belong to, so the page would look something like this:

Name: John Doe
Groups: football, tennis, swimming

Name: Jane Doe
Groups: hockey, basketball

Name: Jim Doe
Groups: hockey, football, rugby

etc. etc.

To accomplish this, I have the following SQL:

SELECT `user`.name, `group`.name 
FROM `user`, `user_group`, `group` 
WHERE `user`.id = `user_group`.user_id 
  AND `group`.id = `user_group`.group_id 
GROUP BY `user`.id, `group`.id

which returns results as follows:

1. John Doe | football
2. John Doe | tennis
3. John Doe | swimming
4. Jane Doe | hockey
5. Jane Doe | basketball
etc. etc.

As you can see, the results returned need to be manipulated in order to produce the comma separated groups shown earlier, as.

Is there a simple way to get the page to display the groups so that they are in a comma separated list for each user in MySQL? Or do I have to write PHP code to loop through the results looking for duplicate IDs and generating the comma-separated lists of groups on the page? Or am I doing something completely wrong in my approach?

Many thanks.

There are a few options (in order of my personal preference).

  1. Don't group by user id, and iterate trough your result and create an multi dimensional array using the user id as a key.
  2. Use GROUP_CONCAT , which isn't pretty.
  3. Use separate queries for selecting all groups + users, and iterate to create an multi dimensional array.

You're in luck. MySQL has a very handy aggregation operator group_concat which allows you to collapse the grouped results into a single row. In your case it would go something like this:

SELECT
  `user`.name,
  GROUP_CONCAT(`group`.group_name)
FROM `user`
INNER JOIN `user_group` ON (`user_group`.user_id = `user`.user_id)
INNER JOIN `group` ON (`group`.group_id = `user_group`.group_id)
GROUP BY `user`.name

It makes no sense to have group_id in your user table if it is many-to-many and you already have a connecting table.

From PHP I guess you use MySQL, so you can use GROUP_CONCAT in situations like this.

Anyway, you are querying a hierarchical structure, which can not gracefully flatted to a single table, so you will always have to do some PHP coding to get the hierchical structure back.

try with GROUP_CONCAT with INNER JOIN

SELECT user.name, GROUP_CONCAT(group.name) FROM user
INNER JOIN user_group ON user.id = user_group.user_id 
INNER JOIN group ON group.id = user_group.group_id 
GROUP BY user.name

This will match your table structure:)

SELECT  `user`.name, GROUP_CONCAT(  `group`.group_name ) 
FROM  `user` 
INNER JOIN  `user_group` ON (  `user_group`.user_id =  `user`.id ) 
INNER JOIN  `group` ON (  `group`.id =  `user_group`.group_id ) 
GROUP BY  `user`.name

HTH:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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