43

I have three tables:

table "package"
-----------------------------------------------------
package_id      int(10)        primary key, auto-increment
package_name    varchar(255)
price           decimal(10,2)

table "zones"
------------------------------------------------------
zone_id         varchar(32)    primary key (ex of data: A1, Z2, E3, etc)

table "package_zones"
------------------------------------------------------
package_id     int(10)
zone_id        varchar(32)

What I'm trying to do is return all the information in package table PLUS a list of zones for that package. I want the list of zones sorted alphabetically and comma separated.

So the output I'm looking for is something like this...

+------------+---------------+--------+----------------+
| package_id | package_name  | price  | zone_list      |
+------------+---------------+--------+----------------+
| 1          | Red Package   | 50.00  | Z1,Z2,Z3       |
| 2          | Blue Package  | 75.00  | A2,D4,Z1,Z2    |
| 3          | Green Package | 100.00 | B4,D1,D2,X1,Z1 |
+------------+---------------+--------+----------------+

I know I could do something in PHP with the presentation layer to get the desired result. The problem is, I would like to be able to sort zone_list ASC or DESC or even use" WHERE zone_list LIKE" and so on. In order to do that, I need this done in MYSQL.

I have NO idea how to even begin to tackle this. I tried using a subquery, but it kept complaining about multiple rows. I tried to concat the multiple rows into a single string, but evidently MySQL doesn't like this.

Thanks in advance.

UPDATE!

Here is the solution for those who are interested.

SELECT 
    `package`.*,
    GROUP_CONCAT(`zones`.`zone` ORDER BY `zones`.`zone` ASC SEPARATOR ','  )  as `zone_list`
FROM 
    `package`,
    `package_zones`
LEFT JOIN 
    (`zones`,`ao_package_zones`) ON (`zones`.`zone_id` = `package_zones`.`zone_id` AND `package_zones`.`package_id` = `package`.`package_id`)
GROUP BY 
    `ao_package`.`package_id`
mrbinky3000
  • 3,835
  • 8
  • 42
  • 53
  • use group by with group_concat on zone field – Haim Evgi Oct 14 '10 at 17:17
  • I used your question updated part select roles.*, GROUP_CONCAT(rp.permission_id SEPARATOR ',') as permission_ids from roles join role_permissions rp on roles.id = rp.role_id GROUP BY roles.id. works – Ozal Zarbaliyev Sep 14 '21 at 09:57

1 Answers1

69

by using the GROUP_CONCAT() function and a GROUP BY call. here's an example query

SELECT 
   p.package_id,
   p.package_name,
   p.price,
   GROUP_CONCAT(pz.zone_id SEPARATOR ',') as zone_list 
FROM 
   package p 
LEFT JOIN package_zone pz ON p.package_id = pz.package_id 
GROUP BY 
   p.package_id

you should still be able to order by zone_id s (or zone_list), and instead of using LIKE, you can use WHERE zp.zone_id = 'Z1' or something similar.

Aran Mulholland
  • 23,006
  • 28
  • 134
  • 225
GSto
  • 40,278
  • 37
  • 127
  • 179
  • So close. Almost there! I'd like zone_list to be sorted alphabetically. That's why I was thinking more along the lines of a subquery. Very close though. – mrbinky3000 Oct 14 '10 at 18:59
  • 1
    Figured out I could put "ORDER BY" in GROUP CONCAT. so GROUP_CONCAT(pz.zone_id ORDER BY pz.zone_id ASC SEPARATOR ',') worked!!!! – mrbinky3000 Oct 14 '10 at 19:06
  • Revision: did not work. It is always returning all the possible zones for each row. Each row should only return the zones for that specific package. – mrbinky3000 Oct 14 '10 at 19:21
  • I figured out how to prevent the return of all possible rows. You had to do a cross join. I will put the answer in the queestion for all to see. – mrbinky3000 Oct 14 '10 at 20:01
  • For anyone how wants to do it in SQL Server: http://stackoverflow.com/questions/6899/is-there-a-way-to-create-a-sql-server-function-to-join-multiple-rows-from-a-su – Mahmood Dehghan Oct 17 '12 at 16:22
  • Perfect... needed to add the group by to specify which column I wanted to group by, otherwise it defaults to the column you are group_concat ing! – Andrew Sep 17 '15 at 14:39