If you just want two rows for each pair of related rooms:
select r1.room 'Room 1',if(which_row=1,min(b1.bed_id),max(b1.bed_id)) 'Bed 1',r2.room 'Room 2',if(which_row=1,min(b2.bed_id),max(b2.bed_id)) 'Bed 2'
from (select 1 which_row union all select 2) which_row
cross join rooms r1
join rooms r2 on r2.room=concat(r1.room,'o')
join beds b1 on b1.room_id=r1.room_id
join beds b2 on b2.room_id=r2.room_id
group by r1.room_id,r2.room_id,which_row
If you want as many rows as there are beds (up to four), it's basically the same but the expression to get the beds for each rows is a little more complicated, and you'll want a subquery to get the number of beds for each room pair:
select
room1 'Room 1',
substring_index(substring_index(beds1, ',', which_row), ',', -1) 'Bed 1',
room2 'Room 2',
substring_index(substring_index(beds2, ',', which_row), ',', -1) 'Bed 2'
from (
select
r1.room room1,
group_concat(distinct b1.bed_id order by b1.bed_id) beds1,
r2.room room2,
group_concat(distinct b2.bed_id order by b2.bed_id) beds2,
least(count(distinct b1.bed_id),count(distinct b2.bed_id)) beds
from rooms r1
join rooms r2 on r2.room=concat(r1.room,'o')
join beds b1 on b1.room_id=r1.room_id
join beds b2 on b2.room_id=r2.room_id
group by r1.room, r2.room
) room_pairs
join (
select 1 which_row union all select 2 union all select 3 union all select 4
) which_row on which_row <= room_pairs.beds
Building it up in pieces, you want each pair of rooms to have up to four rows in the result. So you use a subquery that you can join onto the rest of the query that causes all the other rows to be repeated:
select 1 which_row union all select 2 union all select 3 union all select 4
+-----------+
| which_row |
+-----------+
| 1 |
| 2 |
| 3 |
| 4 |
+-----------+
And a subquery that gets each room pair with all their beds:
select
r1.room room1,
group_concat(distinct b1.bed_id order by b1.bed_id) beds1,
r2.room room2,
group_concat(distinct b2.bed_id order by b2.bed_id) beds2,
least(count(distinct b1.bed_id),count(distinct b2.bed_id)) beds
from rooms r1
join rooms r2 on r2.room=concat(r1.room,'o')
join beds b1 on b1.room_id=r1.room_id
join beds b2 on b2.room_id=r2.room_id
group by r1.room, r2.room
+-------+----------+-------+----------+------+
| room1 | beds1 | room2 | beds2 | beds |
+-------+----------+-------+----------+------+
| A101 | 1,2 | A101o | 7,8 | 2 |
| A102 | 3,4 | A102o | 9,10 | 2 |
| A103 | 5,6 | A103o | 11,12 | 2 |
| A205 | 13,14,15 | A205o | 16,17,18 | 3 |
+-------+----------+-------+----------+------+
Join the two together, limiting the which_row to the number of beds for each room pair:
select which_row, room1, beds1, room2, beds2
from (
select
r1.room room1,
group_concat(distinct b1.bed_id order by b1.bed_id) beds1,
r2.room room2,
group_concat(distinct b2.bed_id order by b2.bed_id) beds2,
least(count(distinct b1.bed_id),count(distinct b2.bed_id)) beds
from rooms r1
join rooms r2 on r2.room=concat(r1.room,'o')
join beds b1 on b1.room_id=r1.room_id
join beds b2 on b2.room_id=r2.room_id
group by r1.room, r2.room
) room_pairs
join (
select 1 which_row union all select 2 union all select 3 union all select 4
) which_row on which_row <= room_pairs.beds
+-----------+-------+----------+-------+----------+
| which_row | room1 | beds1 | room2 | beds2 |
+-----------+-------+----------+-------+----------+
| 1 | A101 | 1,2 | A101o | 7,8 |
| 2 | A101 | 1,2 | A101o | 7,8 |
| 1 | A102 | 3,4 | A102o | 9,10 |
| 2 | A102 | 3,4 | A102o | 9,10 |
| 1 | A103 | 5,6 | A103o | 11,12 |
| 2 | A103 | 5,6 | A103o | 11,12 |
| 1 | A205 | 13,14,15 | A205o | 16,17,18 |
| 2 | A205 | 13,14,15 | A205o | 16,17,18 |
| 3 | A205 | 13,14,15 | A205o | 16,17,18 |
+-----------+-------+----------+-------+----------+
Then just change the selected fields to get the correct bed for each row from the comma-separated list:
select
room1,
substring_index(substring_index(beds1, ',', which_row), ',', -1) bed1,
room2,
substring_index(substring_index(beds2, ',', which_row), ',', -1) bed2
+-------+------+-------+------+
| room1 | bed1 | room2 | bed2 |
+-------+------+-------+------+
| A101 | 1 | A101o | 7 |
| A101 | 2 | A101o | 8 |
| A102 | 3 | A102o | 9 |
| A102 | 4 | A102o | 10 |
| A103 | 5 | A103o | 11 |
| A103 | 6 | A103o | 12 |
| A205 | 13 | A205o | 16 |
| A205 | 14 | A205o | 17 |
| A205 | 15 | A205o | 18 |
+-------+------+-------+------+