简体   繁体   中英

MySQL Dynamic inner join for combining multiple rows into one?

I am creating a database with the tables below, where shop_id in hours refers to a an id in shop.
Preferably I would have a query to return all data in one row, in stead of needing to post-process a lot of rows to "merge" the result from hours so the end result looks like this.

+-------------------+---------+------+---------+----------------+----------+---------------+---------------+-----+-----+-----+-----+-----+-----+-----+
| name              | address | zip  | city    | municipal      | phone    | lat           | lng           | day | day | day | day | day | day | day |
+-------------------+---------+------+---------+----------------+----------+---------------+---------------+-----+-----+-----+-----+-----+-----+-----+
| Coop Marked Budal | false   | 7298 | Budalen | Midtre gauldal | 72436410 | 62.8837013245 | 10.4836997986 |   1 |   2 |   3 |   4 |   5 |   6 |   7 |
+-------------------+---------+------+---------+----------------+----------+---------------+---------------+-----+-----+-----+-----+-----+-----+-----+

Right now I have come to the query below, wich I feel there must be a better alternative to. So my question is: Is there really another solution to this?
Also, I've seen concat, but I want to avoid having to split strings later on when processing the data.

select shop.name, shop.address, shop.zip, shop.city, shop.municipal, shop.phone, shop.lat, shop.lng,
h.day, hh.day, hhh.day, hhhh.day, hhhhh.day, hhhhhh.day, hhhhhhh.day
from shop
/**
As it requires a unique table name, this was the solution I found.
Could this be shortened?
**/
inner join hours h on shop.id = h.shop_id and h.day = 1
inner join hours hh on shop.id = hh.shop_id and hh.day = 2
inner join hours hhh on shop.id = hhh.shop_id and hhh.day = 3
inner join hours hhhh on shop.id = hhhh.shop_id and hhhh.day = 4
inner join hours hhhhh on shop.id = hhhhh.shop_id and hhhhh.day = 5
inner join hours hhhhhh on shop.id = hhhhhh.shop_id and hhhhhh.day = 6
inner join hours hhhhhhh on shop.id = hhhhhhh.shop_id and hhhhhhh.day = 7;

Tables

shop
+----+-------------------+---------+------+---------+----------------+----------+---------------+---------------+----------+-----------+
| id | name              | address | zip  | city    | municipal      | phone    | lat           | lng           | chain_id | county_id |
+----+-------------------+---------+------+---------+----------------+----------+---------------+---------------+----------+-----------+
|  1 | Test              | false   | 1234 | Test    | Test           | 12341234| 0.0000         | 0.0000        |        3 |        16 |
+----+-------------------+---------+------+---------+----------------+----------+---------------+---------------+----------+-----------+


hours
+-----+----------+----------+---------+
| day | open     | close    | shop_id |
+-----+----------+----------+---------+
|   1 | 09:00:00 | 18:00:00 |       1 |
|   2 | 09:00:00 | 18:00:00 |       1 |
|   3 | 09:00:00 | 18:00:00 |       1 |
|   4 | 09:00:00 | 18:00:00 |       1 |
|   5 | 09:00:00 | 18:00:00 |       1 |
|   6 | 09:00:00 | 20:00:00 |       1 |
|   7 | 14:00:00 | 20:00:00 |       1 |
+-----+----------+----------+---------+

You can also use a case .. when to do the pivot, and then group by the shop fields and use an aggregate function to process the day.

select 
    shop.NAME, shop.address, shop.zip, shop.city, shop.municipal, shop.phone, shop.lat, shop.lng,
    MAX(CASE WHEN h.DAY = 1 THEN h.DAY ELSE 0 END) AS Day1,
    MAX(CASE WHEN h.DAY = 2 THEN h.DAY ELSE 0 END) AS Day2,
    MAX(CASE WHEN h.DAY = 3 THEN h.DAY ELSE 0 END) AS Day3,
    MAX(CASE WHEN h.DAY = 4 THEN h.DAY ELSE 0 END) AS Day4,
    MAX(CASE WHEN h.DAY = 5 THEN h.DAY ELSE 0 END) AS Day5,
    MAX(CASE WHEN h.DAY = 6 THEN h.DAY ELSE 0 END) AS Day6,
    MAX(CASE WHEN h.DAY = 7 THEN h.DAY ELSE 0 END) AS Day7
from shop
    INNER JOIN HOURS h ON shop.id = h.shop_id
group by
    shop.NAME, shop.address, shop.zip, shop.city, shop.municipal, shop.phone, shop.lat, shop.lng;

Just a note about what you want displayed in the day columns: AFAIK if any of the hours rows for a shop : day is missing, your current query will drop the whole row? If you want this behaviour repeated, you will need to also add in a where clause.

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