Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Chọn Tất cả sự kiện với Sự kiện-> Lịch biểu-> Ngày giữa ngày bắt đầu và ngày kết thúc trong CakePHP

Trong tình huống này, tôi có xu hướng không sử dụng các liên kết hoặc Có thể chứa của Cake và tự tạo các liên kết:

$events = $this->Event->find('all', array(
    'joins'=>array(
        array(
            'table' => $this->Schedule->table, 
            'alias' => 'Schedule', 
            'type' => 'INNER', 
            'foreignKey' => false,
            'conditions'=> array(
                'Schedule.event_id = Event.id',
            ),
        ),
        array(
            'table' => $this->Date->table, 
            'alias' => 'Date', 
            'type' => 'INNER', 
            'foreignKey' => false,
            'conditions'=> array(
                'Date.schedule_id = Schedule.id',
            ),
        ),
    ),
    'conditions'=>array(
        'Date.start >=' => $start_date,
        'Date.start <=' => $end_date,
    ),
    'order'=>'Event.created DESC',
    'limit'=>5
));

Nó hơi phức tạp, nhưng kết quả là truy vấn chính xác mà tôi muốn.

CẬP NHẬT

Hãy chia mã của bạn thành nhiều phần và xem chúng ta có thể cải thiện nó ở đâu. Phần đầu tiên là chuẩn bị cho find . Tôi đã viết lại mã của bạn để cố gắng làm cho nó ngắn hơn và đây là những gì tôi nghĩ ra:

// Default options go here
$defaultOpts = array(
    'start' => date('Y-m-d') . ' 00:00:00',
    'end' => date('Y-m-d') . ' 23:59:59',
    'limit' => 10
)

// Use default options if nothing is passed, otherwise merge passed options with defaults
$opts = is_array($opts) ? array_merge($defaultOpts, $opts) : $defaultOpts;

// Initialize array to hold query conditions
$conditions = array();

//date conditions
$conditions[] = array(
    "Date.start >=" => $qOpts['start'],
    "Date.start <=" => $qOpts['end'],
));

//cities conditions
if(isset($opts['cities']) && is_array($opts['cities'])) {
    $conditions['OR'] = array();
    $conditions['OR'][] = array('Venue.city_id'=>$opts['cities']);
    $conditions['OR'][] = array('Restaurant.city_id'=>$opts['cities']);
}

//event types conditions
//$opts['event_types'] = array('1');
if(isset($opts['event_types']) && is_array($opts['event_types'])) {
    $conditions[] = 'EventTypesEvents.event_type_id' => $opts['event_types']
}

//event sub types conditions
if(isset($opts['event_sub_types']) && is_array($opts['event_sub_types'])) {
    $conditions[] = 'EventSubTypesEvents.event_sub_type_id' => $opts['event_sub_types']
}

//event sub sub types conditions
if(isset($opts['event_sub_types']) && is_array($opts['event_sub_sub_types'])) {
    $conditions[] = 'EventSubSubTypesEvents.event_sub_sub_type_id' => $opts['event_sub_sub_types']
}

Lưu ý rằng tôi đã loại bỏ hầu hết các OR. Đó là vì bạn có thể chuyển một mảng dưới dạng giá trị trong conditions và Cake sẽ đặt nó thành IN(...) câu lệnh trong Truy vấn SQL. Ví dụ:'Model.field' => array(1,2,3) tạo 'Model.field IN (1,2,3)' . Điều này hoạt động giống như OR, nhưng yêu cầu ít mã hơn. Vì vậy, khối mã ở trên hoạt động giống hệt như mã của bạn đã làm, nhưng nó ngắn hơn.

Bây giờ đến phần phức tạp, find chính nó.

Thông thường, tôi khuyên bạn nên tham gia bắt buộc một mình, không có Containable và với 'recursive'=>false . Tôi tin điều này thường là cách tốt nhất để đối phó với những phát hiện phức tạp. Với Liên kết và Có thể chứa, Cake chạy một số truy vấn SQL đối với cơ sở dữ liệu (một truy vấn cho mỗi Mô hình / bảng), điều này có xu hướng không hiệu quả. Ngoài ra, Containable không phải lúc nào cũng trả về kết quả mong đợi (như bạn đã nhận thấy khi thử).

Nhưng vì trong trường hợp của bạn có bốn các liên kết phức tạp liên quan, có thể một cách tiếp cận hỗn hợp sẽ là giải pháp lý tưởng - nếu không, sẽ quá phức tạp để xóa dữ liệu trùng lặp. (4 liên kết phức tạp là:Event hasMany Dates [thông qua Event hasMany Schedule, Schedule hasMany Date], Event HABTM EventType, Event HABTM EventSubType, Event HABTM EventSubSubType). Vì vậy, chúng tôi có thể để Cake xử lý việc truy xuất dữ liệu của EventType, EventSubType và EventSubSubType, tránh trùng lặp quá nhiều.

Vì vậy, đây là những gì tôi đề xuất:sử dụng các phép nối cho tất cả các bộ lọc bắt buộc, nhưng không bao gồm Ngày và Loại [Phụ [Sub]] trong các trường. Do các liên kết mô hình mà bạn có, Cake sẽ tự động chạy các truy vấn bổ sung đối với DB để tìm nạp các bit dữ liệu đó. Không cần thiết.

Mã:

// We already fetch the data from these 2 models through
// joins + fields, so we can unbind them for the next find,
// avoiding extra unnecessary queries. 
$this->unbindModel(array('belongsTo'=>array('Restaurant', 'Venue'));

$data = $this->find('all', array(
    // The other fields required will be added by Cake later
    'fields' => "
        Event.*, 
        Restaurant.id, Restaurant.name, Restaurant.slug, Restaurant.address, Restaurant.GPS_Lon, Restaurant.GPS_Lat, Restaurant.city_id,
        Venue.id, Venue.name, Venue.slug, Venue.address, Venue.GPS_Lon, Venue.GPS_Lat, Venue.city_id,
        City.id, City.name, City.url_name
    ",  
    'joins' => array(
        array(
            'table' => $this->Schedule->table,
            'alias' => 'Schedule',
            'type' => 'INNER',
            'foreignKey' => false,
            'conditions' => 'Schedule.event_id = Event.id',
        ),
        array(
            'table' => $this->Schedule->Date->table,
            'alias' => 'Date',
            'type' => 'INNER',
            'foreignKey' => false,
            'conditions' => 'Date.schedule_id = Schedule.id',
        ),
        array(
            'table' => $this->EventTypesEvent->table,
            'alias' => 'EventTypesEvents',
            'type' => 'INNER',
            'foreignKey' => false,
            'conditions' => 'EventTypesEvents.event_id = Event.id',
        ),
        array(
            'table' => $this->EventSubSubTypesEvent->table,
            'alias' => 'EventSubSubTypesEvents',
            'type' => 'INNER',
            'foreignKey' => false,
            'conditions' => 'EventSubSubTypesEvents.event_id = Event.id',
        ),
        array(
            'table' => $this->Restaurant->table,
            'alias' => 'Restaurant',
            'type' => 'LEFT',
            'foreignKey' => false,
            'conditions' => 'Event.restaurant_id = Restaurant.id',
        ),
        array(
            'table' => $this->City->table,
            'alias' => 'RestaurantCity',
            'type' => 'LEFT',
            'foreignKey' => false,
            'conditions' => 'Restaurant.city_id = city.id',
        ),
        array(
            'table' => $this->Venue->table,
            'alias' => 'Venue',
            'type' => 'LEFT',
            'foreignKey' => false,
            'conditions' => 'Event.venue_id = Venue.id',
        ),
        array(
            'table' => $this->City->table,
            'alias' => 'VenueCity',
            'type' => 'LEFT',
            'foreignKey' => false,
            'conditions' => 'Venue.city_id = city.id',
        ),
    ),
    'conditions' => $conditions,
    'limit' => $opts['limit'],
    'recursive' => 2
));

Chúng tôi đã loại bỏ contains và một số truy vấn bổ sung mà Cake đã chạy vì nó. Hầu hết các phép nối thuộc loại INNER . Điều này có nghĩa là ít nhất một bản ghi phải tồn tại trên cả hai bảng có liên quan đến phép nối, nếu không bạn sẽ nhận được ít kết quả hơn mong đợi. Tôi giả sử mỗi Sự kiện diễn ra tại một Nhà hàng HOẶC một Địa điểm, nhưng không phải cả hai, đó là lý do tại sao tôi sử dụng LEFT cho các bảng (và thành phố) đó. Nếu một số trường được sử dụng trong các phép nối là tùy chọn, bạn nên sử dụng LEFT thay vì INNER trên các liên kết có liên quan.

Nếu chúng tôi sử dụng 'recursive'=>false ở đây, chúng tôi sẽ vẫn nhận được các sự kiện phù hợp và không có dữ liệu lặp lại, nhưng sẽ thiếu ngày tháng và các loại [Sub [Sub]]. Với 2 mức đệ quy, Cake sẽ tự động lặp lại các sự kiện được trả về và đối với mỗi sự kiện, Cake sẽ chạy các truy vấn cần thiết để tìm nạp dữ liệu mô hình được liên kết.

Đây gần như là những gì bạn đang làm, nhưng không có Điều khiển được và với một vài chỉnh sửa bổ sung. Tôi biết đó vẫn là một đoạn mã dài, xấu xí và nhàm chán, nhưng sau tất cả, có 13 bảng cơ sở dữ liệu liên quan ...

Đây là tất cả mã chưa được kiểm tra, nhưng tôi tin rằng nó sẽ hoạt động.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách Bootstrap MySQL hoặc MariaDB Galera Cluster - Đã cập nhật

  2. mysql sang php sang xml hiển thị tuổi trống

  3. Làm cách nào để chọn hàng dữ liệu đầu tiên và cuối cùng từ kết quả mysql?

  4. Làm cách nào để ngăn chặn việc tiêm sql bằng php và mysql

  5. trước khi chèn trình kích hoạt để chèn các hàng trùng lặp vào một bảng khác