MySQL查找两个日期是否在多行的日期范围之间

时间:2017-07-13 18:58:31

标签: php mysql sql codeigniter date

我正在使用Codeigniter + MySQL + Active Record,我正在建立一个房间价格的时间段项目。

我的mysql表中有以下架构

  

Package_periods

enter image description here

  

Room_package_prices

enter image description here

package_id可以有多个句点,您可以在示例01-08-17 to 08-08-201710-08-2017 to 17-08-2017等中看到。

对于给定的搜索时段(假设为02-08-2017 to 14-08-2017),如何找到package_id不仅超过搜索时段而且搜索时段之外甚至还有1天?

我的意思是,package_id个句点(来自和通过多个mysql行)应涵盖搜索期间的所有日期,而不会留下任何一个空白。

public function getFHotels($checkin = null, $checkout = null, $adults = null, $packageType = null, $package_id = null, $limit, $start, $lang_id) {
        $this->db->select('DISTINCT(hotels.hotel_id)')
                ->from('hotels')
                ->join('rooms', 'rooms.hotel_id=hotels.hotel_id')
                ->where('rooms.room_active', 1)
                ->where('hotels.hotel_active', 1)
                ->limit($limit, $start);

        if ($packageType) {
            $this->db->where('rooms.room_package_id', $packageType);
        }
        if ($package_id && $adults) {
            //if $package_id is given, do not search for checkin-checkout
            $this->db->join('room_package_prices', 'room_package_prices.room_id=rooms.room_id');
            $this->db->where('room_package_prices.package_period_id', $package_id);
            $this->db->where('room_package_prices.adults', $adults);
            $this->db->where('room_package_prices.price>', 0);
        } elseif ($checkin && $checkout && $adults) {
            //if $checkin and $checkout is given, search for the period_from and period_to
            //Here goes my actual question
        }

        $qry = $this->db->get();
        if ($qry->num_rows() > 0)
            return $qry->result_array();
        return FALSE;
    }

1 个答案:

答案 0 :(得分:1)

好的,所以我设法以不同的方式解决这个问题。我想在我的模型函数getFHotels中实现此功能,但无法找到方法。

所以我在控制器中分离了这个功能,并为此目的创建了一个新的模型函数。长话短说,这个想法是

  1. 从客户端
  2. 抓取所需的搜索周期(签入 - 结帐)
  3. 从签到到结帐的每一天循环,并查询每天到桌子,package_id涵盖那一天
  4. 将日常结果推送到数组
  5. 找到数组的相交。如果package_id在数组的每个键中,我就找到了它。
  6. 以下是代码:

            $begin = new DateTime($checkin);
            $end = new DateTime($checkout);
            $interval = DateInterval::createFromDateString('1 day');
            $period = new DatePeriod($begin, $interval, $end);
            $legit_packages = array();
    
            //loop through each day and ask the table if a package_id includes this day
            foreach ($period as $dt) {
                //add each day results in legit_day_packages array
                $legit_day_packages = array();
                $day = $dt->format("Y-m-d");
                //find the packages that include the day
                $periods_found = $this->hotel_model->findFPackagePeriodsPerDay($day);
                if ($periods_found) {
                    //foreach found packages, array push in legit_day_packages the results
                    foreach ($periods_found as $p_f_key => $p_f) {
                        array_push($legit_day_packages, $p_f['package_id']);
                    }
                }
                //Push the legit_day_packages into $legit_packages array. This array will have 1 key per day, containing the package_ids, if found
                array_push($legit_packages, $legit_day_packages);
            }
    
            //Find the intersect package_id. In this was i exclude the 'gaps'. A package_id must appear in every key per day.
            $first = $legit_packages[0];
            for ($i = 1; $i < count($legit_packages); $i++) {
                $result = array_intersect($first, $legit_packages[$i]);
                $first = $result;
            }
    
            //the $result contains all the package_id that satisfies both the range and no 'gap' in the period.
            var_dump($result);
    
      

    模型功能

    public function findFPackagePeriodsPerDay($day) {
            $qry = $this->db->select('packages.package_id')
                    ->from('package_periods')
                    ->join('packages', 'packages.package_id=package_periods.package_id')
                    ->where('packages.is_package_type', 1)
                    ->where('package_periods.period_from<=', $day)
                    ->where('package_periods.period_to>=', $day)
                    ->get();
            if ($qry->num_rows() > 0)
                return $qry->result_array();
            return FALSE;
        }