Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: помогите оптимизировать запросы к базе и возможно логику таблицы

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
exlant
Отправлено: 06 Февраля, 2015 - 06:41:03
Post Id



Посетитель


Покинул форум
Сообщений всего: 425
Дата рег-ции: Февр. 2015  


Помог: 14 раз(а)




при добавлении события можно выбрать периодичность с которой оно будет повторяться(то есть, каждый любой/любые дни недели), выбрать его месторасположение среди других событий, и когда оно начинается и заканчивается.

имеется две таблицы:
1. id, name, period(здесь указывается как будет повторяться событие: каждый день - every_day, в определенные дни недели - week_days), sort(если 0, то это week_days), start, end
2. event_id, Monday,Tuesday,Wednesday, Thursday, Friday, Saturday, Sunday в этой таблице хранится сортировка по дням недели, если 0, то в этом событии, этот день не повторяется( не участвует в сортировке),
сортировка храниться в таком виде - sort(из первой таблицы).сортировка по дням недели( пример 1.001,2.001,2.002)

и так
После ввода даты начала и конца, и периодичности, происходит запрос в базу данных для выбора сортировки:
если периодичность указана как every_day, то запрос выбирает все события, которые соответствуют диапазону дат(начало - конец)
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT `sort`,`name`
  3. FROM `event`
  4. WHERE `period`="every_day" AND ((`start`<=? AND `end`>=?) OR (`end`>=? AND `start`<=?)) OR (`start`>=? AND `end`<=?))
  5. ORDER BY sort
  6.  
  7. $array = array('ssssss',$day_end, $day_end, $day_start, $day_start, $day_start, $day_end);
  8.  

и вывожу списком для определения месторасположения добавляемого события($sort), после этого идет добавление события в базу:
с начало происходит корректировка сортировки:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. UPDATE `event` SET `sort` = `sort` + 1    //добавляем 1 ко всем событиям
  3. WHERE `period`="every_day" AND `user_id`=? AND ((`start`<=? AND `end`>=?) OR (`end`>=? AND `start`<=?) OR (`start`>=? AND `end`<=?))
  4. AND `sort`>= ?; //которые больше или равны выбранного месторасположения
  5. $array = array('ssssssi',$day_end,$day_end,$day_start,$day_start,$day_start,$day_end,$sort)
  6.  
  7.  

потом добавляется само событие
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. INSERT INTO event (name,sort,period,start,end)
  3. VALUES (?,?,?,?,?)
  4. $array = array('sisss', $name,$sort,$period,$data_start,$data_end);
  5.  


если периодичность указана week_days, то пользователь может выбрать любые дни недели для повтора, и что бы пользователь мог выбрать месторасположения нового события, запрос должен выбирать события, которые:
1. соответствуют диапазону дат(начало - конец)
2. повторяются каждый день или по тем же дням, что и добавляемое событие
3. если между начальной и конечной датой(добавляемого события) разница меньше 7ми дней, то исключить те дни недели, которые не совпадают с выбранным диапазоном дат

PHP:
скопировать код в буфер обмена
  1.  
  2. // $days дни в которые должно повторяться событие (например array(0,1,0,1,1,0,0)) то есть массив состоит из 7 элементов, 0 - это Monday, 1- это Tuesday и т.д.
  3. foreach ($days as $key => $value) {
  4.   if($value==1){
  5.      $day = $this->eng_week_days[$key];  // здесь день переводим в английское название
  6.                        
  7.      $query = 'SELECT e.id, e.name, IF(e.sort,e.sort,d.'.$day.') AS new_sort, e.start, e.end FROM event e '
  8.       // IF(e.sort,e.sort,d.'.$day.') если событие повторяется every_day, то sort берется из e.sort, если weeks_days то сорт берется из d.название дня недели
  9.      . 'LEFT OUTER JOIN event_days_of_week d ON d.event_id=e.id '
  10.      . 'WHERE e.user_id=? AND ((e.start<=? AND e.end>=?) OR (e.end>=? AND e.start<=?) OR (e.start>=? AND e.end<=?)) '
  11.     // выбирается совпадающий диапазон дат с такой логикой e.start<=day_start<=e.end или e.start<=day_end<=e.end или e.start<=day_start<=day_end<=e.end
  12.   . 'AND (d.'.$day.' != 0 OR e.period = "every_day") ' // дни которые не участвуют в сортировке
  13.   . 'ORDER BY new_sort ';
  14.                          
  15. $array = array('issssss',parent::$user_id, $day_end, $day_end, $day_start, $day_start, $day_start, $day_end);
  16. $result[$day] = $this->get_data($query, 'assoc', $array);  // запрос к базе
  17. $result[$day] = $this->days_match($result[$day], $day_start, $day_end, $day); // исключить те дни недели,  которые не совпадают с выбранным диапазоном дат
  18. //например есть два диапазона дат 5.01 - 10.01(база) и 10.01 - 15.10(новое) - у них совпал один день, но из базы данных выведутся все дни, которые будут повторяться для этого события
  19. то есть, если 10.01 - это допустим четверг, и только он совпал, но из базы по моему запросу выведутся все дни которые есть у данного события, это с помощью mysql не придумал как сделать, сделал в php
  20. }
  21. }
  22. $_SESSION['new_event']['incorect_week_day'] = $this->incorect_week_day; // дни недели и индексы событий которые не подходят по диапазону дат
  23.  
  24.  
  25. private function days_match($array_db,$start_post,$end_post,$week_day){        
  26.  $start_post = strtotime($start_post);
  27.  $end_post = strtotime($end_post);
  28.            
  29.  foreach($array_db as $key=>$res_value){
  30.    $start_db = strtotime($res_value['start']);
  31.    $end_db = strtotime($res_value['end']);
  32.                
  33.      if($start_db>$start_post AND $end_db>$end_post){                //в диапазон входит только $end_post (start_db < end_post < end_db)
  34.         $days_enter = $end_post - $start_db;
  35.         if(!$this->day_coincidence($days_enter, $start_db, $week_day, $res_value['id'])){ //проверяем или совпал день с диапазоном совпадения дат, если нет то удаляем событие из массива
  36.           unset($array_db[$key]);
  37.         }
  38.        continue;
  39.     }
  40.     if($start_db<$start_post AND $end_db<$end_post){                 //в диапазон входит только $start_post (start_db < start_post < end_db)
  41.     $days_enter = $end_db - $start_post;
  42.      if(!$this->day_coincidence($days_enter, $start_post, $week_day, $res_value['id'])){
  43.       unset($array_db[$key]);
  44.      }
  45.     continue;
  46.     }
  47.     if($start_db>$start_post AND $end_db<$end_post){                //в диапазон входит $start_db и $end_db ($start_post < $start_db $end_db < end_post)
  48.      $days_enter = $end_db - $start_db;
  49.      if(!$this->day_coincidence($days_enter, $start_db, $week_day, $res_value['id'])){
  50.       unset($array_db[$key]);
  51.      }
  52.     continue;
  53.      }
  54.      $array_db[$key]['days_enter'] = 'all';
  55.      }
  56.    return $array_db;
  57. }
  58.  
  59. private function day_coincidence($days_enter, $day_start, $week_day, $event_id){
  60.    $days_enter = (int)($days_enter/60/60/24 + 1);
  61.     if($days_enter<=7){
  62.      $one_day = 60*60*24;
  63.      $add_days = 0;
  64.       for($a=1;$a<=$days_enter;$a++){
  65.        $db_day[] = date('l',$day_start+$add_days);
  66.        $add_days += $one_day;    
  67.        }
  68.        if(in_array($week_day, $db_day)){
  69.        return TRUE;
  70.        }
  71.       $this->incorect_week_day[$week_day][] = $event_id;
  72.       return NULL;
  73.     }
  74.  return TRUE;
  75. }
  76.  
  77.  

выводим список сортировки, пользователь выбирает месторасположение, отсылает нам запрос
PHP:
скопировать код в буфер обмена
  1.  
  2. $incorect_week_day = $_SESSION['new_event']['incorect_week_day'];            //в этот массиве содержатся индекс события и дни недели, которые не вошли в диапазон для сорта ($incorect_week_day[week_day] = array(event_id))
  3.  $query_day_sort_p1 = 'INSERT INTO event_days_of_week (event_id,user_id';     //
  4.  $query_day_sort_p2 = ' VALUES (?,?';  //создаем запрос mysql для вставки в таблицу сортировки по дням недели
  5.                        
  6.  foreach($_POST['sort_after_event'] as $eng_day_week => $sort){
  7.   if(!in_array($eng_day_week, $this->eng_week_days)){                       //
  8.    $this->set_error('add_entry_incorect_period');                        //
  9.   return NULL;     //проверяем валидность присланных данных,
  10.  }
  11.   $sort+= 0.001;  //вставляем наше событие после пришедшего с формы сорта, добавляя к нему 0.001
  12.   $to_query_update_sort = '';   //переменная для добавления в запрос обновления сортировки по дням недели(event_days_of_week)
  13.  if(is_array($incorect_week_day[$eng_day_week])){   //что бы не обновлялась сортировка событий, которые не входят в диапазон дат
  14.    foreach($incorect_week_day[$eng_day_week] as $event_id){
  15.    $to_query_update_sort .= ' AND event_id != '.$event_id;
  16.   }
  17. }
  18.                            
  19.  $query_day_sort_p1 .= ','.$eng_day_week;
  20.  $query_day_sort_p2 .= ','.$sort;
  21.  $this->create_sort($sort,$eng_day_week,$to_query_update_sort);
  22.                            
  23.   }
  24.    $query_day_sort = $query_day_sort_p1.')'.$query_day_sort_p2.')';
  25.    $this->insert_new_event(0,$query_day_sort);
  26.                        
  27.    return TRUE;  
  28.  
  29. function create_sort($sort,$day=NULL,$to_querty_sort='',$operation='+'){
  30. // $operation служит для того что бы, если не вышла вставка события, можно было откатить сортировку назад ($operation = '-')
  31. // сортировка по дням недели осуществляется по дробным числам в диапазоне 0.001 - 1
  32. // запрос обновляет все записи сортировки(+0.001), где совпадает диапазон дат, где есть сортировка(сортировка есть, если в таблице столбик с днем недели не равен 0),
  33. // где сортировка больше или равно $sort и меньше округленной в большую сторону $sort
  34. //
  35.  $query = 'UPDATE `event_days_of_week` SET `'.$day.'` = `'.$day.'` '.$operation.' 0.001 '  
  36.    . 'WHERE event_id IN (SELECT id FROM event WHERE user_id = ? AND (`start`<=? AND `end`>=?) OR (`end`>=? AND `start`<=?) OR (`start`>=? AND `end`<=?)) '
  37.    . 'AND `'.$day.'`!=0 AND `'.$day.'`>=? AND `'.$day.'`< ? '.$to_querty_sort;
  38.   $sort_max = ceil($sort);   // округлил в большую сторону, для того, что бы обновить сортировку только в диапазоне 1, а не все!
  39.  $array = array('issssssdi', parent::$user_id, $day_end,$day_end,$day_start,$day_start,$day_start,$day_end,$sort,$sort_max);
  40.  $result = $this->insert_db($query,$array);
  41.                
  42.  return TRUE;
  43.  
  44.  
  45. }
  46.  
  47. function insert_new_event($sort = 1, $days_query=NULL){    
  48.  $name = $_SESSION['new_event']['name'];
  49.  $text = $_SESSION['new_event']['text'];
  50.  $time = $_SESSION['new_event']['time'];    
  51.  $importance = $_SESSION['new_event']['importance'];        
  52.  $period = $_SESSION['new_event']['period'];
  53.  
  54. $query = 'INSERT INTO event (user_id,name,text,time,sort,importance,period,start,end) '
  55.   . 'VALUES (?,?,?,?,?,?,?,?,?)';
  56.   $array = array('issiissss', parent::$user_id,$name,$text,$time,$sort,$importance,$period,$this->data_start,$this->data_end);
  57.   $result = $this->insert_db($query, $array);
  58.   if(!$result){
  59.   if(empty($days_query)){
  60.    $this->create_sort($sort,NULL,'-');   // откат сортировки
  61.    }else{
  62.      foreach($_POST['sort_after_event'] as $day=>$sort_val){        //
  63.     $sort_val+= 0.001;                                     //
  64.    $this->create_sort($sort_val,$day,'-');                //
  65.    }                                                          // откат сортировки
  66.   }
  67.    $this->set_error('add_entry_mysql_error');
  68.    return NULL;
  69.  }
  70.  if($this->sort_type == 'days'){
  71.  $days_array = array('ii',$this->insert_last_id,  parent::$user_id);
  72.  $days_result = $this->insert_db($days_query, $days_array);
  73.  if(!$days_result){
  74.  foreach($_POST['sort_after_event'] as $day=>$sort_val){        //
  75.  $sort_val+= 0.001;                                     //
  76.    $this->create_sort($sort_val,$day,'-');                //
  77.  }                // откат сортировки
  78.    $query = 'DELETE FROM event WHERE id='.$this->insert_last_id;  // удаляем добавленное событие
  79.    return NULL;
  80.  }
  81. }
  82.  unset($_SESSION['new_event']);
  83.  $_SESSION['new_event_add'] = 'TRUE';
  84.   header('location:'.DOMEN.$_SERVER['REQUEST_URI']);
  85.   die();
  86.                          
  87. }
  88.  
  89.  


как лучше организовать логику таблиц, и запросов к ней в данной ситуации??
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB