2013-09-10 4 views
0

У меня есть некоторые данные в серии баз данных SQLite с различными связанными таблицами. Каждая таблица имеет столбец начала и окончания, представляющий диапазон дат, для которого каждая запись действительна. Базы данных SQLite в основном доступны с использованием библиотеки C# и System.Data.SQLite.Операции с диапазоном дат

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

SELECT a.field, max(a.start, b.start) as start, min(a.end, b.end) as end 
FROM a 
INNER JOIN b 
ON a.field = b.field AND NOT(a.start > b.end OR b.start > a.end); 

Но я не уверен, как получить периоды времени а, где она не имеет соответствия б. Это легко получить записи в которой нет перекрытия:

SELECT a.field, a.start, a.end 
FROM a 
LEFT JOIN b 
ON a.field = b.field AND NOT(a.start > b.end OR b.start > a.end) 
WHERE b.field is NULL; 

Но о том, где они пересекаются, или б разбивает на две записи? Показаны диапазоны дат, как сроки, как я получаю c в a-b=c зависимости, показанной ниже (строки представляют собой диапазоны дат отдельных записей в таблицах a и b, и результирующий набор c)

a: |-----------------| |--------| |--------||-----| 
b:  |---|     |--------| 
c: |-----|  |-----| |-----|   |---||-----| 

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

+0

попробовали что-то вроде этого: WHERE condition BETWEEN lower_range AND upper_range –

+0

[SQL: 2011] (http://en.wikipedia.org/wiki/SQL:2011) выглядит многообещающим. Может быть, мне просто нужно очистить свой C и добавить некоторые из этих функций в SQLite самостоятельно. – AndASM

ответ

2

Пара указателей:

  • Убедитесь, что значения являются либо временные метки, основанные на UTC, или только целые календарные даты. Это делается для того, чтобы избежать проблем с часовыми поясами и летним временем.

  • Используйте полуокрытые интервалы, [start, end). Это позволит избежать проблемы двух смежных диапазонов, содержащих одно и то же значение. Другими словами:

    • start <= value < end
    • start <= value && end > value

  • Вы могли бы рассмотреть возможность использования Noda Time. Он имеет тип Interval, который представляет эту скважину. Но в настоящее время в нем не так много операций.

  • Вы также можете рассмотреть возможность использования Time Period Library for .NET, который имеет огромный количество определенных операций. Просто будьте осторожны, чтобы все ваши значения DateTime, которые вы используете с ним, имеют DateTimeKind.Utc за их значение .Kind. Если вы попытаетесь использовать локальные типы, это будет неправильно вести себя. Другими словами, не пропустите DateTime.Now.

  • Конечно, нет необходимости использовать любая библиотека. Вы всегда можете определить свою собственную структуру или класс, чтобы содержать диапазон. Для этого нет ничего построенного, нет.

  • Запрос Вы писали, что хорошо для обнаружения совпадений, но вы можете упростить ее немного:

    Вместо этого: NOT(a.start > b.end OR b.start > a.end)
    это сделать: a.start < b.end AND b.start < a.end

    Это логически эквивалентны, но будет выполняются немного лучше, как запрос.

Я не знаю, как непосредственно ответить на ваши вопросы, хотя. Не совсем понятно, что вы просите. В частности, в этом последнем примере два диапазона c уже существуют в таблице, и вы хотите их вернуть? Или вы хотите построить их из расчета между a и b? Если последнее, вероятно, лучше всего сделать эту часть в C#, а не в SQL.

+0

«Как мне получить c (две записи) в a-b = c« Я имею в виду, как мне построить c из a и b. Как выполнить запрос, чтобы найти диапазоны дат a, которые не пересекаются с b для какой-либо произвольной связи между a и b. Когда я говорю «две записи», я имею в виду, что c может представлять две или меньше записей, зависящих, если b содержится в a, частично перекрывается с a или полностью покрывает a. – AndASM

+0

Вы можете построить 'c' в своем коде C#. Я бы не попытался это сделать в SQL. Но для запроса, каковы входные параметры? Вы хотите * все * диапазоны дат, которые не имеют совпадений? Или вы передаете единую дату или дату начала и окончания? –

+0

Я ищу общий случай здесь. Другими словами, в моих входных данных a может представлять один или несколько непересекающихся диапазонов дат, а b может представлять нулевые или более непересекающиеся диапазоны дат. Я хочу найти нулевые или более непересекающиеся диапазоны c, которые являются результатом удаления всех перекрывающихся диапазонов между a и b. – AndASM

0

Используя Time Period Library for .NET вы можете прочитать периоды времени в коллекции и применить TimeGapCalculator, TimePeriodCombiner или TimePeriodSubtractor утилиты для оценки требуемых пробелов и дублирования.