О своем: SQL-хозяйке на заметку

Jul 29, 2007 00:21

Сугубо о своем...

Иногда в программировании БД возникает задача регистрировать "периоды" в широком смысле: период имеет срок действия "с" и "по". Иногда есть желание хранить начало и конец периода (действие документа, период отчетности, период работы аудитора и т.п.) в двух колонках таблицы. (Понятно, что можно не хранить "избыточные" данные, храня только начала очередного периода и конец последнего периода в одной колонке, но по разным причинам эту идею приходится в каких-то случаях отвергать). Если выбран вариант хранения "с" и "по" (в двух колонках), может возникнуть задача контроля смежности/непрерывности разных периодов - например, чтобы каждый последующий период начинался строго на следующий день после окончания предыдущего, т.е. чтобы не было пересечений периодов и "незаполненных дырок". Условие такого контроля можно решить изящным способом. Если, скажем, в таблице имеются два поля p_start и p_end, обозначающие начало и конец периода, то выражение в следующей выборке SELECT:

SELECT DATEDIFF(day, MIN(p_start), MAX(p_end))
- COUNT(*) + 1
- SUM(DATEDIFF(day, p_start, p_end))
FROM dbo.MyTable

равно нулю тогда и только тогда, когда имеющиеся периоды строго смежные (без перекрытий и дырок). Смысл: (если речь вести о к-ве дней) интервал в днях между началом самого раннего периода и концом самого позднего должен равняться сумме интервалов всех периодов с точностью до слагаемого COUNT(*)-1 (к-во периодов без 1-цы), которое возникает из-за того, что начало каждого следующего периода есть следующий день после окончания предыдущего периода.
Модификацией при необходимости NULL-значений (при пустых выборках) и предложения GROUP BY (когда периоды привязаны к некоторым объектам) можно запендюрить контроль на уровне БД (триггеры или - это хуже - ограничения CONSTRAINT) таблиц на смежность периодов. О как.

sql

Previous post Next post
Up