Hello for the first time!
In my effort to become a better programmer I decided to build an online booking web application. As you can see in the picture below, I have created this database with the following things in mind.
- each customer may book an appointment or request an appointment. - i) Booked appointments have a fixed time and day. - ii) Appointment requests do not have a fixed time and day until they are booked manually through the back office. They must have at least two time-ranges between two days, or more which declare when the customer is available, so the appointment must be booked inside one of these time ranges. 
- each appointment may have more than one customers ( probably max to 3 ) 
- each customer may have more than one services ( haven't decided the limit here )
The desired outcome for the front-end, I have decided upon is the following (which will have pagination and ajax as well but I am not there yet):
The first successful attempt on this, was not efficient at all as I needed to run 4 queries to the database for each appointment, so I immediately started thinking of something better but I wasted almost two weeks and I have nothing yet.
I can't understand in which part I am missing knowledge MySQL or PHP(forgot to mention that I am writing this with PHP but better late than never)....very likely on both sides but I don't know what to study to solve this one, while so many other stuff I managed to find something around.
Thanks in advance!
UPDATE: Follows the code I use (including the queries):
MODEL
 public function getAppointments()
    {
        $db = \Config\Database::connect();
        // get future appointments
        $query = $db->query('
                            SELECT DISTINCT`appointment_id` 
                            FROM `appointments_schedule`
                            WHERE `datetime_from` > CURRENT_TIMESTAMP
                            ');
        $appointments = $query->getResultArray();
        return $appointments;
    }
    public function getAppointmentDateTimes($appointment_id)
    {
        $db = \Config\Database::connect();
        $query = $db->query('
                            SELECT `datetime_from`, `datetime_to`
                            FROM `appointments_schedule`
                            WHERE `appointment_id` = ' . $appointment_id
                            );
        $appointmentDateTimes = $query->getResultArray();
        return $appointmentDateTimes;
    }
    public function getAppointmentCustomers($appointment_id)
    {
        $db = \Config\Database::connect();
        $query = $db->query('
                            SELECT `id`, `last_name`, `first_name`, customers.status, `is_booking`
                            FROM customers
                            INNER JOIN appointment_customer_services ON appointment_customer_services.customer_id = customers.id
                            WHERE id IN(
                                        SELECT `customer_id`
                                        FROM appointment_customer_services
                                        WHERE appointment_id = ' . $appointment_id . ')
                            GROUP BY customers.last_name'                                
                            );
        $appointmentCustomers = $query->getResultArray();
        return $appointmentCustomers;
    }
    public function getCustomerServices($appointment_id, $customer_id)
    {
        $db = \Config\Database::connect();
        $query = $db->query('
                            SELECT `name` AS `service_name`
                            FROM services
                            WHERE id IN(SELECT `service_id`
                                        FROM appointment_customer_services
                                        WHERE `customer_id` =' . $customer_id . ' 
                                        AND `appointment_id` =' . $appointment_id . ')
                            ');
        $CustomerServices = $query->getResultArray();
        return $CustomerServices;
    }
CONTROLLER
$data['appointments'] = [];
    foreach ( $model->getAppointments() as $appointment )
    {
        foreach ( $appointment as $id )
        {
            foreach ( $model->getAppointmentDateTimes($id) as $key => $timeDates )
            {
                $data['appointments'][$id]['timeDates'][] = $timeDates;
            }
            foreach ( $model->getAppointmentCustomers($id) as $appointmentCustomers )
            {                   
                foreach ( $model->getCustomerServices($id, $appointmentCustomers['id']) as $services )
                {
                    foreach ( $services as $service )
                    {
                        $appointmentCustomers['services'][] = $service;
                    }
                }
                $data['appointments'][$id]['customers'][] = $appointmentCustomers;
            }
        }
    }
PRINT_R OUTPUT
Array
(
    [1] => Array
        (
            [timeDates] => Array
                (
                    [0] => Array
                        (
                            [datetime_from] => 2020-04-28 14:00:00
                            [datetime_to] => 2020-04-28 17:00:00
                        )
                    [1] => Array
                        (
                            [datetime_from] => 2020-05-06 12:00:00
                            [datetime_to] => 2020-05-06 17:00:00
                        )
                    [2] => Array
                        (
                            [datetime_from] => 2020-05-30 17:00:00
                            [datetime_to] => 2020-05-30 20:00:00
                        )
                )
            [customers] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [last_name] => Jolie 
                            [first_name] => Angelina 
                            [status] => 1
                            [is_booking] => 1
                            [services] => Array
                                (
                                    [0] => service1
                                )
                        )
                )
        )
    [2] => Array
        (
            [timeDates] => Array
                (
                    [0] => Array
                        (
                            [datetime_from] => 2020-05-29 14:00:00
                            [datetime_to] => 2020-05-29 16:00:00
                        )
                )
            [customers] => Array
                (
                    [0] => Array
                        (
                            [id] => 2
                            [last_name] => Lopez
                            [first_name] => Jennifer
                            [status] => 1
                            [is_booking] => 1
                            [services] => Array
                                (
                                    [0] => service1
                                    [1] => service2
                                    [2] => service3
                                )
                        )
                )
        )
    [3] => Array
        (
            [timeDates] => Array
                (
                    [0] => Array
                        (
                            [datetime_from] => 2020-05-28 15:00:00
                            [datetime_to] => 2020-05-27 17:00:00
                        )
                )
            [customers] => Array
                (
                    [0] => Array
                        (
                            [id] => 3
                            [last_name] => Charlize
                            [first_name] => Theron
                            [status] => 1
                            [is_booking] => 1
                            [services] => Array
                                (
                                    [0] => service1
                                    [1] => service2
                                    [2] => service3
                                )
                        )
                    [1] => Array
                        (
                            [id] => 4
                            [last_name] => Bullock
                            [first_name] => Sandra
                            [status] => 1
                            [is_booking] => 0
                            [services] => Array
                                (
                                    [0] => Service1
                                    [1] => Service2
                                )
                        )
                    [2] => Array
                        (
                            [id] => 5
                            [last_name] => Aniston
                            [first_name] => Joe
                            [status] => 1
                            [is_booking] => 0
                            [services] => Array
                                (
                                    [0] => service1
                                )
                        )
                )
        )
)
VIEW(the table i fill with the data above)
<table class="table table-hover">
                      <thead class="text-warning">
                        <?php foreach ( $table_head as $th) : ?>
                            <th <?php if ($th == "timeDates"){echo "style="."text-align:center;";} ?>>
                              <?php echo $th; ?>
                            </th>
                        <?php endforeach; ?>
                      </thead>
                      <tbody>
                      <?php
                      /*  the table has 3 cells and does not contain nested tables
                          each row represents one customer, with his services in a unordered list
                          the times cell has a rowspan = the number of the appointment customers                              
                      */
                      ?>
                      <?php foreach ( $appointments as $appointment ) : ?>
                      <tbody class="appointments-table">
                          <?php foreach ( $appointment['customers'] as $index => $customer) : ?>
                          <tr class="appointments-table">
                              <td <?php echo $customer['is_booking'] ? "style='font-weight: bold;'" : ''; ?>><?php echo $customer['last_name'] . ' ' . $customer['first_name'];?></td>
                              <td>
                                  <?php foreach ( $customer['services'] as $service ) : ?>
                                  <ul style="list-style-type:none; padding-left: 0; margin-bottom: 0;">
                                      <li><?php echo $service; ?></li>
                                  </ul>
                                  <?php endforeach; ?>
                              </td>
                              <?php if ( $index == 0 ) : ?>
                              <td class="appointments-table" rowspan=<?php echo count($appointment['customers']); ?>>
                                  <ul class="pl-0 mb-0" style="list-style-type:none; text-align: center; margin-bottom: 0;">
                                    <?php foreach ( $appointment['timeDates'] as $timeDate ) : ?>
                                    <li><?php echo $timeDate['datetime_to'] ? 
                                                  ( date_format(date_create($timeDate['datetime_from']), "d/m/Y H:i") . ' until ' . 
                                                  date_format(date_create($timeDate['datetime_to']), "d/m/Y H:i") ) : 
                                                  date_format(date_create($timeDate['datetime_from']), "d/m/Y H:i"); ?></li>
                                    <?php endforeach; ?>
                                  </ul>
                              </td>
                              <?php endif; ?>
                          </tr>
                          <?php endforeach; ?>
                      </tbody>
                      <?php endforeach; ?>
                    </table>
NOTE: i intend to improve the view also to move as much logic as possible to the controller
 
    