PHP Time Filtering и MYSQL-фильтрация - PullRequest
       12

PHP Time Filtering и MYSQL-фильтрация

3 голосов
/ 18 декабря 2011

У меня есть 3 столбца: Day, start_schedule и end_schedule.

   Day  |  start_schedule | end_schedule
 -------|-----------------|--------------
 Monday |     1:00        |   3:00
 Monday |     6:00        |   8:00
 Monday |     8:00        |  10:00

Я все еще изучаю php.Как я буду фильтровать, если мое начальное и конечное расписание ввода является действительным на основании сохраненного времени в базе данных?

Например, если я хочу добавить времена

  • start_schedule = 3:00 and end_schedule = 7:00

, поскольку существует 6:00 - 8:00, вам не разрешено добавлять это расписание.

  • start_schedule = 7:00 и end_schedule =11:00

, поскольку есть 6:00 - 8:00 и 8:00 - 10:00, вам не разрешено добавлять это расписание.

Ответы [ 3 ]

2 голосов
/ 18 декабря 2011

Я бы выполнил большую часть логики в mysql, так как он будет обрабатывать такие выражения очень просто и просто.

В PHP перед вставкой новой записи нам потребуетсячтобы проверить 1 вещь:

  1. Является ли end_time меньше start_time?Если это так, прервите.

В MySQL при попытке вставить новую запись нам нужно будет проверить 4 вещи:

  1. Является ли start_time внутри какой-либо существующей записи?Если это так, прервите.
  2. Находится ли end_time внутри какой-либо существующей записи?Если это так, прервите.
  3. Есть ли какая-либо запись, начинающаяся с нашей новой записи?Если это так, прервите.
  4. Есть ли какая-либо запись окончания, которая будет внутри нашей новой записи?Если это так, прервите.

Вышесказанное может быть фактически реорганизовано в один шаг:

  1. Есть ли наше время начала меньше, чем время окончания любых записей, И наше время окончаниябольше, чем время начала?Если это так, прервите.

mysql> describe sample;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| start | time        | YES  |     | NULL    |       |
| end   | time        | YES  |     | NULL    |       |
| day   | varchar(50) | YES  |     | Monday  |       |
+-------+-------------+------+-----+---------+-------+

mysql> SELECT * FROM sample;
+--------+----------+----------+
| day    | start    | end      |
+--------+----------+----------+
| Monday | 01:00:00 | 03:00:00 |
| Monday | 06:00:00 | 08:00:00 |
| Monday | 08:00:00 | 11:00:00 |
+--------+----------+----------+

Пример реализации в PHP запроса к базе данных:

Переход к @ regilero для публикацииперефакторизованная версия условия where требуется.

$new_entries = array (
  array('Monday', '00:00:00', '23:59:00'),
  array('Monday', '12:00:00', '15:00:00'),
  array('Monday', '07:00:00', '10:00:00')
);

foreach ($new_entries as $new) {
  list ($day, $start, $end) = $new;

  $q_day   = "'$day'";
  $q_end   = "'$end'";
  $q_start = "'$start'";

  $sql = <<<EOQ
    INSERT INTO `sample` (day,start,end)
    SELECT $q_day, $q_start, $q_end FROM DUAL
    WHERE NOT EXISTS (
      SELECT * FROM `sample`
      WHERE day = $q_day AND (
        $q_start < end AND $q_end > start
      )
    )
EOQ;

  mysql_query ($sql) or die (mysql_error ());

  if (mysql_affected_rows () == 0)
    print join (' ', $new) . " was not inserted!\n";
  else
    print join (' ', $new) . " was inserted!\n";
}

Это приведет к выводу:

Monday 00:00:00 23:59:00 was not inserted!
Monday 12:00:00 15:00:00 was inserted!
Monday 07:00:00 10:00:00 was not inserted!
2 голосов
/ 18 декабря 2011

Если это хранилище MySQL, вам нужно выполнить запрос SQL для получения записей, которые перекрывают вашу текущую новую запись, прежде чем вы даже попытаетесь вставить новую запись.Затем, если ваша проверка на совпадение не возвращает ни одной строки, вы можете безопасно вставить свою строку (если все это сделано в транзакции, иначе кто-то мог бы вставить что-то между вашей проверкой и вашей вставкой, выполните транзакции и вставьте блокирует в таблице, чтобы никто не мог вставить, пока вы проверяете и вставляете).

В основном, чтобы найти перекрывающуюся строку, вам нужен такой запрос (myday mystart и myend - новые значенияВы хотите вставить):

SELECT count(*)
 FROM mytable
 WHERE Day=myday
  AND mystart < end_schedule
  AND myend > start_schedule

Этот запрос может быть оптимизирован, если у вас есть много записей, которые нужно просто выполнить, и СУЩЕСТВУЕТ операция вместо счетчика (так как требуется 1 перекрывающийся период, чтобы решить, что вам не следует продолжать).

Теперь, если у вас есть несколько графиков, наложенные друг на друга дни буксировки более сложны.На самом деле вы не можете хранить тезисы в вашей модели базы данных.Если я хочу начать воскресенье в 22:00 и закончить понедельник в 04:00 или даже в четверг в 06:00 ... Так что, возможно, вы разбиваете свои графики, чтобы вставить несколько расписаний, по одному в день.Тогда вам нужно будет тщательно проверить, чтобы все ваши части расписаний могли быть вставлены, а не только одна из них.И, конечно, все еще выполняет все эти вещи в транзакции.

РЕДАКТИРОВАТЬ:

тест перекрытия:

     s------------------------e
  s1----------e1
                        s2----------e2
         s3----------e3
  • s < e1
  • s < e2
  • s < e3
  • e > s1
  • e > s2
  • e > s3
0 голосов
/ 18 декабря 2011

Я бы порекомендовал метод типа MySQL TIME, если вы можете.Вот метод в PHP, однако, в случае, если он вам нужен.

Обратите внимание, что он зависит от времени, которое находится в 24-часовых часах, что означает, что 22:00 равно 10pm.Кроме того, я не воспринимаю 0:00 как полночь с этим кодом, и он не охватывает несколько дней (т. Е. 22:00 и 5:00).Это просто простая проверка в тот же день, и она преобразует времена в целочисленные представления, а затем сравнивает времена как числа.

Вам также необходимо выяснить, как вы собираетесь получить свое собственное $schedules настройка массива.Вы можете передать его в качестве другого аргумента, например.

РЕДАКТИРОВАТЬ

Подход, основанный на том, что Regilero использует:

function checkNewTime($day, $start, $end, &$error) {
    $_start = str_replace(':', '', $start);
    $_end = str_replace(':', '', $end);
    $error = '';
    $schedules = array(
        'Monday' => array(
            array('1:00', '3:00'),
            array('6:00', '7:00'),
            array('8:00', '10:00')
        )
    );

    if ($_end <= $_start) {
        $error = "The new start time ($start) cannot be after the end time ($end).";
        return false;
    }

    $schedules = $schedules[$day];
    $c_schedules = count($schedules);

    for ($i = 0; $i < $c_schedules; $i++) {
        $interval = "{$schedules[$i][0]} and {$schedules[$i][1]}";

        $interval_start = str_replace(':', '', $schedules[$i][0]);
        $interval_end = str_replace(':', '', $schedules[$i][1]);

        if ($_start < $interval_end && $_end > $interval_start) {
            $error = "The start is between schedules time $interval.";
            return false;
        }

    }

    return true;
}

http://codepad.org/hznpATft

Функция:

function checkNewTime($day, $start, $end, &$error) {
    $_start = str_replace(':', '', $start);
    $_end = str_replace(':', '', $end);
    $error = '';
    $schedules = array(
        'Monday' => array(
            array('1:00', '3:00'),
            array('6:00', '8:00'),
            array('8:00', '10:00')
        )
    );

    if ($_end <= $_start) {
        $error = "The new start time ($start) cannot be after the end time ($end).";
        return false;
    }

    $schedules = $schedules[$day];
    $c_schedules = count($schedules);

    for ($i = 0; $i < $c_schedules; $i++) {
        $interval = "{$schedules[$i][0]} and {$schedules[$i][1]}";

        $interval_start = str_replace(':', '', $schedules[$i][0]);
        $interval_end = str_replace(':', '', $schedules[$i][1]);

        if ($_start > $interval_start && $_start < $interval_end) {
            $error = "The start is between schedules time $interval.";
        }

        if ($_end < $interval_end && $_end > $interval_start) {
            $error .= " The end is between schedule times $interval.";
        }

        if ($_start < $interval_start && $_end > $interval_end) {
            $error .= " The schedule encapsulates the schedule times $interval.";
        }

        if ($error != '') return false;
    }

    return true;
}

Контрольный пример:

$times = array(
    array('5:00','8:00'),
    array('3:30','6:00'),
    array('4:30','5:00'),
    array('5:30','7:00'),
    array('9:00','10:00'),
    array('9:30','11:00'),
    array('21:30','12:00'),
    array('11:30','11:30'),
    array('12:30','20:00'),
    array('15:30','18:00'),
    array('12:30','19:00'),
    array('19:30','24:00'),
    array('17:30','23:45')
);

$c_times = count($times);
$error = '';

for ($i = 0; $i < $c_times; $i++) {
    if (checkNewTime('Monday', $times[$i][0], $times[$i][1], $error)) {
        echo "{$times[$i][0]}, {$times[$i][1]} does not conflict.\n\n";
    } else {
        echo "{$times[$i][0]}, {$times[$i][1]} does conflict.\nError: $error\n\n";
    }
}

http://codepad.org/pEq9Wdh4

Выходы:

5:00, 8:00 does conflict.
Error:  The schedule encapsulates the schedule times 6:00 and 7:00.

3:30, 6:00 does not conflict.

4:30, 5:00 does not conflict.

5:30, 7:00 does conflict.
Error:  The end is between schedule times 6:00 and 8:00.

9:00, 10:00 does conflict.
Error: The start is between schedules time 8:00 and 10:00.

9:30, 11:00 does conflict.
Error: The start is between schedules time 8:00 and 10:00.

21:30, 12:00 does conflict.
Error: The new start time (21:30) cannot be after the end time (12:00).

11:30, 11:30 does conflict.
Error: The new start time (11:30) cannot be after the end time (11:30).

12:30, 20:00 does not conflict.

15:30, 18:00 does not conflict.

12:30, 19:00 does not conflict.

19:30, 24:00 does not conflict.

17:30, 23:45 does not conflict.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...