2016-10-21 1 views
1

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

 UID SmallRangeStart smallRangeEnd  BigRangeStart  BigRangeEnd 
     1  01 15 2016  01 20 2016  01 17 2016   02 30 2016 

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

+0

Какую версию SQL вы используете (MySQL, SQL Server и т.д.)? –

+0

Сначала убедитесь, что вы сохраняете даты с использованием типа данных даты – Strawberry

+0

Какая СУБД вы используете? И эти 4 столбца в 1 строке? Или это распределено по 2 строкам с 2 столбцами? Или 4 строки с 1 столбиком? Также: '02 30 2016' является недопустимой датой. 30 февраля –

ответ

0

Логика, которую вы хотите использовать, состоит в том, что перекрытие равно нулю, если два диапазона не пересекаются вообще. Это произойдет, если малый диапазон начался и закончился доBigRangeStart или малый ряд начался и закончился послеBigRangeEnd. В противном случае, если имело место некоторое перекрытие, то вы хотите взять разницу между больше из SmallRangeStart и BigRangeStart и меньше из SmallRangeEnd и BigRangeEnd.

Вот решение MySQL:

SELECT CASE WHEN SmallRangeEnd < BigRangeStart THEN 0 
      WHEN SmallRangeStart > BigRangeEnd THEN 0 
      ELSE DATEDIFF(GREATEST(SmallRangeStart, BigRangeStart), 
          LEAST(SmallRangeEnd, BigRangeEnd)) 
     END AS days_in_range 
FROM yourTable 

Запрос также не меняется при переходе на SQL Server:

SELECT CASE WHEN SmallRangeEnd < BigRangeStart THEN 0 
      WHEN SmallRangeStart > BigRangeEnd THEN 0 
      ELSE DATEDIFF(day, 
          CASE WHEN SmallRangeStart > BigRangeStart 
           THEN SmallRangeStart ELSE BigRangeStart END, 
          CASE WHEN SmallRangeEnd < BigRangeEnd 
           THEN SmallRangeEnd ELSE BigRangeEnd END) 
     END AS days_in_range 
FROM yourTable 
+0

Спасибо, что это сработало! – daf3131

1

Для базы данных MySQL вы можете использовать функцию DATEDIFF

 select datediff('2016-09-15','2016-09-12') 

этот запрос вернется 3

для базы данных MSSQL можно использовать (только вычитание)

SELECT DATEDIFF(day,'2007-05-06 12:10:09','2007-05-07 12:10:09') 

вернет 1

Для оракула Вы можете использовать

SELECT TO_DATE('2000-01-02', 'YYYY-MM-DD') - 
    TO_DATE('2000-01-01', 'YYYY-MM-DD') AS DateDiff 

С двойной

Для PostgreSQL: вы можете использование

SELECT DATE_PART('day', '2011-12-31 01:00:00'::timestamp - '2011-12-29 23:00:00'::timestamp); 

- он возвращает: 1

0

Это идеально подходит для типов диапазона Postgres':

Если у вас есть четыре столбца в одной строке, сначала вычислить пересечение два диапазона, используя:

daterange(smallrangestart, smallrangeend) * daterange(bigrangestart, bigrangeend) as overlap 

Это дает перекрытие двух диапазонов. Из нового диапазона вы просто вычтите нижнюю границу от верхней границы

верхний (перекрытие) - нижний (перекрытие);

Так что все утверждение было бы:

select upper(daterange(smallrangestart, smallrangeend) * daterange(bigrangestart, bigrangeend)) - 
     lower(daterange(smallrangestart, smallrangeend) * daterange(bigrangestart, bigrangeend)) 
from the_table 
where uid = 1;