Исправлена версия ответа @Farkie, специально предназначенная для проверки простых чисел в циклах.
function isPrime_v2($num) {
static $knownPrimes=[3]; // array to save known primes
if($num == 1)
return false;
if($num == 2 || $num == 3) //added '3'
return true;
if($num % 2 == 0)
return false;
$ceil = ceil(sqrt($num)); //same purpose, good point from Farkie
// Check against known primes to shorten operations
// There is no sense to check agains numbers in between
foreach($knownPrimesas $prime){
if ($prime>$ceil)
break;
if($num===$prime)
return true;
if($num % $prime == 0)
return false;
}
/**
* end($knownPrimes) % 2 !==0 - mathematically guaranteed
* start with latest known prime
*/
for($i = end($knownPrimes)+2; $i <= $ceil; $i = $i + 2) {
if($num % $i == 0)
return false;
}
$knownPrimes[]=$num;
return true;
}
Тест с phpfiddle.org. V1 - ответ Farkie, V2 - расширенная версия
V1 (1 to 5,000,000): divisions=330 929 171; primes=348 513; time=21.243s
V2 (1 to 5,000,000): divisions=114 291 299; primes=348 513; time=10.357s
ПРИМЕЧАНИЕ! Функция
blockquote>isPrime_v2
применима ТОЛЬКО в случае петли с 3. В противном случае сохраненный массив $ knownPrimes будет иметь недостаточную историю.
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(event_id SERIAL PRIMARY KEY
,name VARCHAR(12) NOT NULL
,start_dt DATETIME NOT NULL
,end_dt DATETIME NULL
);
INSERT INTO my_table VALUES
(1, 'Carnival', '2018-04-30 12:00:00','2018-04-30 12:00:00'+INTERVAL 150 MINUTE),
(2, 'Fairytale','2018-04-30 20:00:00','2018-04-30 20:00:00'+INTERVAL 200 MINUTE);
SELECT * FROM my_table;
+----------+-----------+---------------------+---------------------+
| event_id | name | start_dt | end_dt |
+----------+-----------+---------------------+---------------------+
| 1 | Carnival | 2018-04-30 12:00:00 | 2018-04-30 14:30:00 |
| 2 | Fairytale | 2018-04-30 20:00:00 | 2018-04-30 23:20:00 |
+----------+-----------+---------------------+---------------------+
INSERT INTO my_table (name,start_dt,end_dt)
SELECT 'Whatever','2018-04-20 11:58:00','2018-04-30 13:00'
FROM (SELECT 1) x
LEFT
JOIN my_table y
ON y.end_dt > '2018-04-30 11:58:00'
AND y.start_dt < '2018-04-30 13:00:00'
WHERE y.event_id IS NULL;
SELECT * FROM my_table;
+----------+-----------+---------------------+---------------------+
| event_id | name | start_dt | end_dt |
+----------+-----------+---------------------+---------------------+
| 1 | Carnival | 2018-04-30 12:00:00 | 2018-04-30 14:30:00 |
| 2 | Fairytale | 2018-04-30 20:00:00 | 2018-04-30 23:20:00 |
+----------+-----------+---------------------+---------------------+