How to do a select with multiple results in a single row

1

The problem: One of our sites has a system of messages between users, for this we have two tables: one that stores messages between users and another with users, follow the structures below , and with this data we need to display in the messages the name of all users to which the message was sent.

At first I thought about making a select for the messages and with the id of the users of this message to generate another select's string within a while , but this seemed wrong and searching the internet I found no alternative to this situation. Would anyone have a solution to this problem? Would you like to make a single select to get both the name of the users and the message?

Following structures:

TABLE messages:

  • id INT PRIMARY KEY,
  • id_users: 'Relates to user id, Ex: 1,27,1247,88',
  • title 'message title',
  • text 'message text',

TABLE users:

  • id INT PRIMARY KEY,
  • name 'user name',
  • etc.
asked by anonymous 03.07.2014 / 18:51

3 answers

2

Even though you create an SQL for this, it will cost you a lot of processing, as you will have to break this string id_users into a list, and make a JOIN on it.

What I suggest is that you redo your structure, using the way most systems work in this situation. This way:

TABLE messages:

id INT PRIMARY KEY,
title 'titulo da mensagem',
text 'texto da mensagem',

TAB users:

id INT PRIMARY KEY,
name 'nome do usuario',

users_messages:

id INT PRIMARY KEY
id_user (FK)
id_mensagem (FK)

It is a super basic Many-to-Many structure, meaning a message can belong to 1 or more users, and a user can have 1 or more messages. With this, your query looks like this:

SELECT u.id, u.name, m.id
    FROM users u
    JOIN users_mensagens um ON um.id_users = u.'id'
    JOIN mensagens m ON m.id = um.id_mensagens;
    
03.07.2014 / 18:53
2

A friend (@rodrigoborth) helped me by talking about 'FIND_IN_SET', which made me arrive at the following query:

SELECT mensagens.id, users.name, mensagens.title, mensagens.date
    FROM mensagens INNER JOIN users
        WHERE FIND_IN_SET( users.id , mensagens.id_users ) ORDER BY mensagens.id

Simplifying my problem and so temporarily answering the question! =)

    
03.07.2014 / 19:26
1

Your database seems denormalized, I advise if possible, creating a table to relate the user to the message. But it follows an option by using a subquery to bring users related to the message, reducing the number of query result rows.

SELECT
m.title,
m.text,
m.id_users,
(
  SELECT 
  GROUP_CONCAT(u.name SEPARATOR ';')
  FROM users u 
  WHERE FIND_IN_SET(u.id,m.id_users)
) as nomes
FROM mensagens m

In this case the query returns the users related to the message in the format usuario1;usuário2

Example: SQLFiddle

    
03.07.2014 / 19:38