如何编写mySQL查询以在前端组成表?

问题描述 投票:-1回答:1

第一次问好!

为了成为一名更好的程序员,我决定构建一个在线预订Web应用程序。如您在下图中所看到的,我在创建数据库时考虑了以下几点。

  1. 每个客户都可以预约或要求预约。

    i)预定的约会有固定的日期和时间。

    ii)约会请求没有固定的时间和日期,直到通过后台。他们必须在两天之间至少有两个时间范围,或者更长,以声明何时客户可用,因此必须在以下时间范围之一内预定约会。

  2. 每个约会可能有一个以上的客户(可能最多3个)

  3. 每个客户可能有多个服务(这里尚未确定限制)

my database

我确定的前端的理想结果是以下内容(也将具有分页和ajax,但我还没有出现):

front-end table

第一次成功的尝试完全没有效率,因为我需要为每个约会对数据库运行4个查询,所以我立即开始考虑更好的方法,但是我浪费了将近两个星期,但是我什么都没有。

我不明白我缺少哪一部分的MySQL或PHP知识(忘了说我正在用PHP编写它,但是迟到总比没有好。。。。。)学习解决这个问题,而我设法找到了很多其他东西。

提前感谢!

更新:遵循我使用的代码(包括查询):

模型

 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
                                )

                        )

                )

        )

)

查看(我用上面的数据填满的表)

<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>

注意:我打算改善视图,以便将尽可能多的逻辑移至控制器

php mysql
1个回答
0
投票

现在我们可以看到您的查询,是的,您的预感是正确的-这不是一种有效的方法。这是所谓的n+1 problem的示例,其中您对父记录(SELECT)进行了初始appointments,然后对每个记录(n)进行了另外一个SELECT(或(在这种情况下,还有更多),以查找有关这些记录的相关数据。

[另一个注释,SELECT .. WHERE IN ( ... subquery ... ) is very slow。如果可以的话,请尽量避免这种情况。

您的架构似乎已经很好地规范化了,那么为什么不使用某些SELECT .. WHERE IN ( ... subquery ... )? AFAICT您应该可以通过单个查询找到所需的内容。所有联接均位于主键上,这些主键均为JOIN,因此这应该很有效率。

这是您仅通过查询您的查询就得出的表中最简单,最幼稚的联接。您可能需要进行一些INT处理,或将GROUP BY更改为JOIN,或进行其他一些调整...我不知道您的数据或架构,因此这只是使您入门的第一步。当然,它不会以您当前使用的格式生成结果,我的意思是嵌套数组等-您必须更新前端才能显示它。但这最终会更简单。

INNER JOIN
© www.soinside.com 2019 - 2024. All rights reserved.