views:

84

answers:

2

This is a follow-up question to my previous one.
Situation:

Table 1:
+--------------------+--------------------+
|               v_id |             v_name |
+--------------------+--------------------+
|                  1 |            v_name1 |
+--------------------+--------------------+
| etc...

Table 2:
+--------------------+--------------------+
|               a_id |             a_name |
+--------------------+--------------------+
|                  1 |            a_name1 |
+--------------------+--------------------+
| etc...

Table 3:
+--------------------+--------------------+
|               v_id |               a_id |
+--------------------+--------------------+
|                  1 |                  1 |
+--------------------+--------------------+
|                  1 |                  2 |
+--------------------+--------------------+
|                  1 |                  3 |
+--------------------+--------------------+

I want to get a join of the two tables:

SELECT t1.*, t2.a_name
FROM `table1` t1
LEFT JOIN `table_3` t3 ON t3.v_id = t1.v_id
LEFT JOIN `table_2` t2 ON t2.a_id = t3.a_id
WHERE t1.id = 1;

The result of this query will be 3 rows for the given tables, each row with the same values from Table 1, just a different a_name from Table 3.
Now, is it possible for me to make a_name an array (of 3 cells in this case)? I think that this is not possible. If it's not, how would I have to build the query so that it would return just one row, with the a_name results joined with a given 'glue' string?


EDIT If I were to get a result in PHP, I would expect something like:

$result = array(
    'v_id'    => 1,
    'a_name'  => array('a_name1', 'a_name2', 'a_name3')
);

or

$result = array(
    'v_id'    => 1,
    'a_name'  =>'a_name1, a_name2, a_name3'), # assuming I used ', ' as the glue string
);
+1  A: 

I believe you are looking for the GROUP_CONCAT function.

In your query it would look like this:

SELECT t1.*, GROUP_CONCAT(t2.a_name SEPARATOR ',')
FROM `table1` t1
LEFT JOIN `table_3` t3 ON t3.v_id = t1.v_id
LEFT JOIN `table_2` t2 ON t2.a_id = t3.a_id
WHERE t1.id = 1
GROUP BY [list of t1 columns here] 
-- update thanks to OMG Ponies.
Sean Vieira
thank you. that does the trick good enough for me! appreciated!
Michal M
one observation though. this solution works just fine for one row only. if we get rid of `WHERE` clause it will not produce valid results.
Michal M
@Michal M: It's missing a `GROUP BY` clause. MySQL, in it's infinite wisdom, allows for omitting columns from the `GROUP BY` and still working - no other db I'm aware of allows this, and causes pain (there's lots of "why does this work on MySQL but not DB XYZ..." on SO). You need to list every column that is not wrapped in an aggregate function (GROUP_CONCAT in this case) in the `GROUP BY`. Here's the MySQL page about missing columns: http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html
OMG Ponies
@Michal and @OMG Ponies: Updated. Thanks for the catch!
Sean Vieira
+2  A: 

Use:

    SELECT t1.*, 
           GROUP_CONCAT(DISTINCT t2.a_name SEPARATOR ',')
     FROM `table1` t1
LEFT JOIN `table_3` t3 ON t3.v_id = t1.v_id
LEFT JOIN `table_2` t2 ON t2.a_id = t3.a_id
   WHERE t1.id = 1
 GROUP BY [list of t1 columns here]

Sean Viera's answer works as you pointed out because of the WHERE clause, and because MySQL allows for columns to be omitted from the GROUP BY. It's not a good habit - only MySQL allows this, and such queries will not port to other databases (there's lots of examples on SO).

I added the distinct in the GROUP_CONCAT - didn't think you want duplicates if any exist.

OMG Ponies