z[j].n <= z[j].m <= z[j].o
(z[i].n / z[j].n) = (z[i].m / z[j].m) = (z[i].o / z[j].o)
(z[i].n / z[j].n) = (z[i].m / z[j].m) => ((z[i].n * z[j].m) / (z[i].m * z[j].n)) = 1
(z[i].n / z[j].n) = (z[i].o / z[j].o) => ((z[i].n * z[j].o) / (z[i].o * z[j].n)) = 1
abs(((z[i].n * z[j].m) / (z[i].m * z[j].n)) - 1) < epsilon &&
abs((z[i].n * z[j].o) / (z[i].o * z[j].n)) - 1) < epsilon
SELECT `a`.*
FROM `articles` AS `a`
JOIN (
SELECT GROUP_CONCAT(DISTINCT `tag_id` ORDER BY `tag_id`) AS `tags`
FROM `articleTags`
WHERE `article_id` = :articleId
) AS `at`
JOIN (
SELECT GROUP_CONCAT(DISTINCT `tag_id` ORDER BY `tag_id`) AS `tags`, `article_id`
FROM `articleTags`
GROUP BY `article_id`
) AS `st` ON `st`.`article_id` = `a`.`id` AND `st`.`tags` = `at`.`tags`
$intervals =
[['start' => '2017-01-01', 'end' => '2017-01-06'],
['start' => '2017-01-21', 'end' => '2017-01-30'],
['start' => '2017-01-10', 'end' => '2017-01-20'],
['start' => '2017-01-05', 'end' => '2017-01-16'],
['start' => '2017-01-15', 'end' => '2017-01-20']];
function is_intersect($int1, $int2) {
return ($int2['end'] >= $int1['start'] && $int1['end'] >= $int2['start']);
}
function combine($int1, $int2) {
if (!isset($int1['subintervals'])) {
$int1['subintervals'] = [$int1];
}
if (!isset($int2['subintervals'])) {
$int2['subintervals'] = [$int2];
}
return array('start' => min($int1['start'], $int2['start']), 'end' => max($int1['end'], $int2['end']),
'subintervals' => array_merge($int1['subintervals'], $int2['subintervals']));
}
function combine_intersected($intervals) {
$result = [];
$noIntersects = true;
foreach ($intervals as $int1) {
$combined = false;
foreach ($result as &$int2) {
if (is_intersect($int1, $int2)) {
$int2 = combine($int1, $int2);
$noIntersects = false;
$combined = true;
break;
}
}
if (!$combined) {
$result[] = $int1;
}
}
if ($noIntersects) {
return false;
}
return $result;
}
while ($ints = combine_intersected($intervals)) {
$intervals = $ints;
}
Array (
[0] => Array (
[start] => 2017-01-01
[end] => 2017-01-20
[subintervals] => Array (
[0] => Array (
[start] => 2017-01-10
[end] => 2017-01-20
)
[1] => Array (
[start] => 2017-01-15
[end] => 2017-01-20
)
[2] => Array (
[start] => 2017-01-05
[end] => 2017-01-16
)
[3] => Array (
[start] => 2017-01-01
[end] => 2017-01-06
)
)
)
[1] => Array (
[start] => 2017-01-21
[end] => 2017-01-30
)
)