Подтвердить что ты не робот

Обнаружение совпадающих диапазонов дат из одной таблицы

У меня есть таблица со следующими данными

PKey  Start       End         Type
====  =====       ===         ====
01    01/01/2010  14/01/2010  S
02    15/01/2010  31/01/2010  S
03    05/01/2010  06/01/2010  A

И хочу получить следующие результаты

PKey  Start       End         Type
====  =====       ===         ====
01    01/01/2010  14/01/2010  S
03    05/01/2010  06/01/2010  A

Любые идеи о том, с чего начать? Многое из чтения, которое я сделал, предполагает, что мне нужно создавать записи и каждый день и присоединяться к совпадающим дням, это единственный способ?

4b9b3361

Ответ 1

Если у вас уже есть записи за каждый день, который должен работать, но если вы не накладные расходы значительны, и если этот запрос используется часто, это повлияет на производительность.

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

select dr1.* from date_ranges dr1
inner join date_ranges dr2
on dr2.start > dr1.start -- start after dr1 is started
  and dr2.start < dr1.end -- start before dr1 is finished

Если вам нужна специальная обработка для интервала, который полностью находится в пределах другого интервала, или вам нужно слить интервалы, т.е.

PKey  Start       End         Type
====  =====       ===         ====
01    01/01/2010  20/01/2010  S
02    15/01/2010  31/01/2010  S

получая

Start       End         Type
=====       ===         ====
01/01/2010  31/01/2010  S

вам понадобится более сложный расчет.

В моем опыте с такими проблемами, как только вы получите, как делать вычисления вручную, легко передать его в SQL:)

Ответ 2

Может быть:

SELECT A.PKey, A.Start, A.End, A.Type
FROM calendar AS A, calendar AS B
WHERE (p.pkey<>a.pkey
AND b.start>=a.start
AND b.end<=a.end)
OR (b.pkey<>a.pkey
AND b.start<=a.start
AND b.end>=a.end)

Ответ 3

Когда мне нужно было сравнить два временных интервала в SQL для перекрытия, вот четыре сценария, о которых я мог подумать:

  • Начало Span1 начинается между запуском Span2 и концом Span2
  • Конец Span1 находится между запуском Span2 и концом Span2
  • Начало и конец Span1 - между запуском Span2 и концом Span2
  • Начало и конец Span2 находятся как между запуском Span1, так и концом Span1

Вот оператор OR, который я создал для захвата этих сценариев (в моем случае Oracle SQL):

and (
    s1.start between s2.start and s2.end
    OR
    s1.end between s2.start and s2.end
    OR
    s2.start between s1.start and s1.end
)

Ответ 4

select A.*
from MyTable A
inner join MyTable B
on (B.start <= A.end)
and (B.end >= A.start)

или что-то в этом роде (предполагая, что даты не являются нулевыми, а равные даты считаются перекрытием).

Ответ 5

Я должен был сделать очень похожее дело, чтобы остановить повторный праздник, который был введен в таблицу. он был в доступе и написан на соблазнительный вход, поэтому пришлось запросить его в VBA SQL:

 stCommandText = "SELECT " _
                    & "* " _
                    & "FROM " _
                    & "TableName a, " _
                    & "TableName b " _
                    & "WHERE " _
                    & "a.ID = b.ID " _
                    & "AND a.Startdate >= b.Startdate AND a.StartDate <= b.EndDate " _
                    & "AND a.AutoNo <> b.AutoNo "

Ответ 6

Мы все давно нуждались в таком перекрывающемся предикате в наших запросах, и я думаю, что нашел очень простое решение здесь.

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

Чтобы сделать это, я пошел со следующим утверждением предиката:

AND @_expiration >= EffectiveDate AND ExpirationDate >= @_effective

Надеюсь, кто-то найдет это полезным, как я.

Ответ 7

В MySQL вам в основном нужно:

SELECT COUNT(*) FROM date_ranges AS A, date_ranges AS B WHERE A.id <> B.id AND A.id > B.id AND A.end_at > B.start_at AND B.end_at > A.start_at

> во втором и третьем операторах можно заменить на >=, чтобы следовать включению соответствия.

Этот раздел связан с "Алленной алгеброй Аллена", и есть еще некоторые сведения об этом можно найти по этим ссылкам:

Ответ 8

BTW - Если у вас нет уникального идентификатора, против ваших дат вы можете сделать это, оракул.. FYI

with date_ranges
as
(
SELECT 
     rownum as pkey,
    date_ranges.*
FROM  date_ranges
) 
select 
dr1.* 
from 
date_ranges dr1 , date_ranges dr2
where  dr1.pkey > dr2.pkey
AND dr1.end_dt >= dr2.start_dt 
AND dr2.end_dt >= dr1.start_dt

Ответ 9

Sql = 'SELECT task_id, task_start_date, task_due_date FROM (wba_task) WHERE (task_start_date <= "2016-07-13" AND task_due_date >= "2016-07- 25" ) ИЛИ (task_due_date МЕЖДУ "2016-07-13" и "2016-07-25" ) ';

Запрос Codeigniter ниже.

$fromdaysDate="2016-07-13";//changed date
$todaysDate="2016-07-25";//changed date
$this->db->select('task_id,task_start_date, task_due_date'); 
$this->db->where('task_start_date <="'.date('Y-m-d', strtotime($fromdaysDate)).'"');
$this->db->where('task_due_date >="'.date('Y-m-d', strtotime($todaysDate)).'"');    
$this->db->or_where('task_due_date BETWEEN "'. date('Y-m-d', strtotime($fromdaysDate)). '" and "'. date('Y-m-d', strtotime($todaysDate)).'"');   
$alltask=$this->db->get('wba_task')->result_array();
echo $this->db->last_query();

получить всю базу данных данных перекрытия.... введите описание изображения здесь