PHP + MYSQL优化复杂查询

时间:2018-10-15 11:53:09

标签: php mysql performance calculation

尊敬的Stackoverflow成员,

我的问题

我在MYSQL中需要以下帮助: 对于出租住宿的网站,我需要计算房间的可用性。

一种情况: 用户想在2018年10月21日预订7人的住宿,共8人。 然后,系统需要查找所有在住宿期间每天可容纳8人的房间的住宿。这可以是房间的任意组合。

我的表结构(仅必要的列):

项目(带住宿的桌子): ID

可用性: id | fkItemRoom | arrival_date | arrival_possible | departure_possible |分配

item_room: id | fkItemId | fkRoomId

房间: id | max_occupancy

可用性表中的每一行都是带有物料室的日期,该日期指示该日期是否有分配。因此,要计算7个晚上的可用性,一个房间需要在可用性表中有7行,连续7天为该物料室分配该空间。

我当前的解决方案:

此解决方案返回所有可用的容纳空间,并且使用SUM,我采取了一些方法来计算可用性。我知道这不是正确的方法。

        $vars['allotment'] = 8;
        $vars['duration'] = $duration;
        $ids = array();
        $availableParts = array();
        $allotmentParts = array();
        $wParts = array();
        foreach($arrivalDates as $key => $date) {
            $durationDates = array();
            for($i = 0; $i < $duration; $i++) {
                $durationDates[] = strtotime(date('11:00 d-m-Y',strtotime("+ $i days",$date['from'])));
            }

            $arrivalDate = $date['from'];
            $departureDate = $date['till'];
            $availableParts[] = "(SELECT count(id) FROM availability ea WHERE ea.arrival_date IN(".implode(',',$durationDates).") AND ea.allotment > :allotment AND ea.fkItemRoom = ir.id)";
            $allotmentParts[] = "(SELECT SUM(ea.allotment * r.max_occupancy) FROM availability ea WHERE ea.arrival_date IN(".implode(',',$durationDates).") AND ea.allotment > 0 AND ea.fkItemRoom = ir.id)";
            $wParts[] = "(ir.id IN (SELECT fkItemRoom FROM availability ea WHERE ea.arrival_date = $arrivalDate AND ea.arrival_possible = 1 AND ((ea.is_maximum IS NULL AND ea.minimum_stay <= :duration) OR (ea.is_maximum = 1 AND ea.minimum_stay = :duration)))
                        AND 
                        ir.id IN (SELECT fkItemRoom FROM availability ea WHERE ea.arrival_date = $departureDate AND ea.departure_possible = 1))";
        }

        $query = " 
            SELECT
                ir.fkItemId,
                GREATEST(".implode(',', $availableParts).",-1) as total_available,
                GREATEST(".implode(',', $allotmentParts).",-1) as total_allotment
            FROM 
                item_room ir
            INNER JOIN
                room r
            ON 
                r.id = ir.fkRoomId
            WHERE 
                (".implode(' OR ', $wParts).") 
            GROUP BY
                ir.fkItemId 
            HAVING 
                total_available >= :duration AND total_allotment >= :allotment";

我需要此解决方案来考虑可伸缩性和性能。 如果需要更多信息,请询问,我会提供。

该脚本是用PHP 7.2和MYSQL编写的。

如果您不懂PHP:

php代码在每个时段(从开始日期到结束日期)都会生成多个查询。用户可以选择在+-2天内获得结果。然后,主查询接受所有这些子查询,并将它们与php函数“ implode”一起放入mysql“ GREATEST”函数。此时,查询仅需要知道是否存在一个具有足够可用天数和分配量的期间。

免责声明

我不是在寻找可以给我完美算法的人。我想学习和理解如何处理这种情况。创建一个视图,将其拆分为多个查询,重新考虑我的整个数据库结构。这只是许多其他复杂情况中的一种现实情况。

0 个答案:

没有答案