powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Непересекающиеся интервалы
15 сообщений из 15, страница 1 из 1
Непересекающиеся интервалы
    #37441876
khus-2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день уважаемые участники форума! Подскажтье как лучше разрулить такую проблему.
Есть таблица EntityTable(ID number, BeginDate DATE, EndDate DATE). Надо чтобы разные сущности не пересекались по периуду действия BeginDate, EndDate. Минимальная гранулярность дат - один день.
Как лучше сделать? Есть мысль сделать дополнительную такую табличку EnUseDay(ID number, UseDate DATE) куда для каждого дня в которые действует сущность вставлять строчку. Так данных побольше будет, но и надежнее. ИМХО, конечно. Покритикуйте плиз подход.
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37441953
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А почему бы не убрать даты начала и конца вообще? Оставить только время действия. Времена
действия сущностей считать строго последовательными или разрывы между ними заполнять
"псевдосущностью".
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37442013
khus-2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov,

Быстро же тут отвечают. ) Спасибо за ответ. Про "псевдосущность" не подумал, но есть проблема, что сущности могут быть удалены. Появяться разрыва. Хотя разрывы можно заполнять "псевдосущностями" конечно. Но как будет выглядеть запросы к такой табле? Например, вывести список сущностей действоваших в период с 01.01.2011 по 31.01.2011?
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37442042
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
khus-2011Например, вывести список сущностей действоваших в период с 01.01.2011 по 31.01.2011?

Придётся оконные функции задействовать чтобы вычислять сумму длительностей с нарастающим
итогом.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37442132
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну или убрать у сущности дату окончания действия и считать, что она действует пока ей на
замену не придёт следующая. Запросы будут чуть попроще.

Или вообще не париться и проверять непересечение интервалов триггерами при
вставке/изменении, блокируя от записи на это время всю таблицу. Это если модификаций мало.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37442343
SERG1257
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну не все так мрачно
Во первых наложите ограничение BeginDate <= EndDate
Во вторых желательно (чтобы упростить запросы и не писать isnull(EndDate,'9999')) сделать EndDate not null default far_in_future
Далее пересечение интервалов возможно при четырех условиях
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
 1 
*----*
---*---*
 2 
---*---*--
*----*
 3 
*-------*
--*---*---
 4 
--*---*---
*-------*
запрос на получение пересекающихся интервалов
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select * from EntityTable t1
where exists 
(select * from EntityTable t2 on t1.Entity_id=t2.Entity_id
and (
    (t1.BeginDate < t2.EndDate and t1.EndDate<t2.EndDate)
or (t2.BeginDate < t1.BeginDate and t2.EndDate < t1.EndDate)
or (t1.BeginDate < t2.BeginDate and t2.EndDate < t1.EndDate)
or (t2.BeginDate < t1.BeginDate and t1.EndDate < t2.EndDate)
  )
)
Либо же интервалы НЕ пересекаются если соблюдается условия
Код: plaintext
1.
2.
3.
4.
5.
6.
 1 
--*----*--------------
-------------*------*--
 2 
-------------*------*--
--*----*--------------
select * from EntityTable t1
where NOT exists
(select * from EntityTable t2 on t1.Entity_id=t2.Entity_id
and (
(t1.BeginDate < t2.BeginDate and t1.EndDate<t2.EndDate)
or (t2.BeginDate < t1.BeginDate and t2.EndDate<t1.EndDate)
)
)
авторНапример, вывести список сущностей действоваших в период с 01.01.2011 по 31.01.2011?
опять же либо пересекаемся с интервалом 01.01.2011 по 31.01.2011
Код: plaintext
1.
2.
3.
4.
-----b-----e--
*-------*----
*--------------*
-------*-*------
-------*------*

либо не выводить сущьности не пересекающиеся с интервалом
Код: plaintext
1.
2.
3.
-----b-----e--
*-*----------
--------------*--*
Написать запросы будет домашним заданием

Конечно использовать одну дату change_date вместо BeginDate, EndDate менее избыточно, а стало быть менее противоречиво, но во первых для получения сущностей на произвольную дату требуется два прохода по таблице,
во вторых дай первую запись (select top 1 ... в MSSQL или select ... where rownum=1 в оракле) не стандартизирована и в каждой субд реализована по своему.
Короче, как всегда, можно оптимизировать либо чтение либо запись
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37442950
_VVP_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SERG1257Либо же интервалы НЕ пересекаются если соблюдается условия
Код: plaintext
1.
2.
3.
4.
5.
 1 
--*----*--------------
-------------*------*--
 2 
-------------*------*--
--*----*--------------
(t1.BeginDate < t2.BeginDate and t1.EndDate<t2.EndDate) or (t2.BeginDate < t1.BeginDate and t2.EndDate<t1.EndDate)
Условие записано неверно.

Интервалы НЕ пересекаются при соблюдении следующих условий:
Код: plaintext
1.
(Окончание1 < Начало2) ИЛИ (Начало1 > Окончания2)
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37442971
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
khus-2011Добрый день уважаемые участники форума! Подскажтье как лучше разрулить такую проблему.
Есть таблица EntityTable(ID number, BeginDate DATE, EndDate DATE). Надо чтобы разные сущности не пересекались по периуду действия BeginDate, EndDate. Минимальная гранулярность дат - один день.
Как лучше сделать? Есть мысль сделать дополнительную такую табличку EnUseDay(ID number, UseDate DATE) куда для каждого дня в которые действует сущность вставлять строчку. Так данных побольше будет, но и надежнее. ИМХО, конечно. Покритикуйте плиз подход.


А надо...это при выборке или при вставке?
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37443317
khus-2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем спасибо за ответы, уважаемые!! )
Озверинkhus-2011Добрый день уважаемые участники форума! Подскажтье как лучше разрулить такую проблему.
Есть таблица EntityTable(ID number, BeginDate DATE, EndDate DATE). Надо чтобы разные сущности не пересекались по периуду действия BeginDate, EndDate. Минимальная гранулярность дат - один день.
Как лучше сделать? Есть мысль сделать дополнительную такую табличку EnUseDay(ID number, UseDate DATE) куда для каждого дня в которые действует сущность вставлять строчку. Так данных побольше будет, но и надежнее. ИМХО, конечно. Покритикуйте плиз подход.


А надо...это при выборке или при вставке?Ну надо, чтобы в таблице не было пересечений. Это выходит при выборке и вставке, вместе наверно. Подробнее задача такая. Требуется исключить малейшую возможность пересечения строк по интервалам. При конкурентном доступе есть небольшая вероятность, что по интервалам это может произойти потому, что одна сессия не видит данных другой сессии до коммита. Используется Оракл. Блокировать всю таблицу не вариант.
А если делать вставку в отдельную таблицу то этого произойти не может, не даст первичный ключ этому произойти. Поправте если неправ я с СУБД недавно работаю. Кстати я с начала думал что для каждого дня вставлять строку это дорого обойдется а для нескольких лет мгновенно делается не больше 16 милисекуню. Надо несколько из нескольких тредов проверить как это выглядеть будет.
авторНаписать запросы будет домашним заданиемЭто даже такой двоишнег как я сделает )))
SELECT * FROM ENTITYTABLE ET
WHERE ET.BEGINDATE BETWEEN '2011-01-01' AND '2011-01-31' OR ET.ENDDATE BETWEEN '2011-01-01' AND '2011-01-31'
Это так за январь выбираем
_VVP_SERG1257Либо же интервалы НЕ пересекаются если соблюдается условия
Код: plaintext
1.
2.
3.
4.
5.
 1 
--*----*--------------
-------------*------*--
 2 
-------------*------*--
--*----*--------------
(t1.BeginDate < t2.BeginDate and t1.EndDate<t2.EndDate) or (t2.BeginDate < t1.BeginDate and t2.EndDate<t1.EndDate)
Условие записано неверно.

Интервалы НЕ пересекаются при соблюдении следующих условий:
Код: plaintext
1.
(Окончание1 < Начало2) ИЛИ (Начало1 > Окончания2)
Для полноты не хватает еще условий Начало1 < Окончания1 и Начало2 < Окончания2. Но это подразумевается уже заранее. Условие пересечения я так делал
ET1.BEGINDATE BETWEEN ET2.BEGINDATE AND ET2.ENDDATE OR ET1.ENDDATE BETWEEN ET2.BEGINDATE AND ET2.ENDDATE
Если not добавить то получим непересечения интервалов
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37443473
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
khus-2011Всем спасибо за ответы, уважаемые!! )
Озверинпропущено...



А надо...это при выборке или при вставке?Ну надо, чтобы в таблице не было пересечений. Это выходит при выборке и вставке, вместе наверно. Подробнее задача такая. Требуется исключить малейшую возможность пересечения строк по интервалам. При конкурентном доступе есть небольшая вероятность, что по интервалам это может произойти потому, что одна сессия не видит данных другой сессии до коммита. Используется Оракл. Блокировать всю таблицу не вариант.
А если делать вставку в отдельную таблицу то этого произойти не может, не даст первичный ключ этому произойти. Поправте если неправ я с СУБД недавно работаю. Кстати я с начала думал что для каждого дня вставлять строку это дорого обойдется а для нескольких лет мгновенно делается не больше 16 милисекуню. Надо несколько из нескольких тредов проверить как это выглядеть будет.
авторНаписать запросы будет домашним заданиемЭто даже такой двоишнег как я сделает )))
SELECT * FROM ENTITYTABLE ET
WHERE ET.BEGINDATE BETWEEN '2011-01-01' AND '2011-01-31' OR ET.ENDDATE BETWEEN '2011-01-01' AND '2011-01-31'
Это так за январь выбираем
_VVP_пропущено...
Условие записано неверно.

Интервалы НЕ пересекаются при соблюдении следующих условий:
Код: plaintext
1.
(Окончание1 < Начало2) ИЛИ (Начало1 > Окончания2)
Для полноты не хватает еще условий Начало1 < Окончания1 и Начало2 < Окончания2. Но это подразумевается уже заранее. Условие пересечения я так делал
ET1.BEGINDATE BETWEEN ET2.BEGINDATE AND ET2.ENDDATE OR ET1.ENDDATE BETWEEN ET2.BEGINDATE AND ET2.ENDDATE
Если not добавить то получим непересечения интервалов

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

Для "хохмы" потребуется доп таблица, которая только нормализует вашу базу, впринципе )
Справочник дней (дат), начиная с даты по умолчанию(1970 год 01.01 например) последовательно:
Calendar
id | date

Код: plaintext
1.
2.
3.
4.
5.
6.
SELECT id, cal.id AS cid
FROM (SELECT id, begin_date_id as date_id
FROM tbl
UNION
SELECT id, end_date_id AS date_id
FROM tbl) AS data, Calendar cal
WHERE cal.id BETWEEN (SELECT Max(date_id) FROM data AND SELECT Min(date_id) FROM data )

этот запрос нам дает в итоге множество "дат" для каждой сущности :)
остается сгруппировать коды по кол-ву "дат" >1


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
SELECT data.id
FROM (SELECT id, begin_date_id as date_id
	FROM entity
	UNION
	SELECT id, end_date_id AS date_id
	FROM entity) AS data, Calendar cal
WHERE cal.id <= (
	SELECT Max(date_id) 
	FROM (SELECT id, begin_date_id as date_id
	FROM entity
	UNION
	SELECT id, end_date_id AS date_id
	FROM entity) t1
	) 
AND cal.id >= (
	SELECT Min(date_id) 
	FROM (SELECT id, begin_date_id as date_id
	FROM entity
	UNION
	SELECT id, end_date_id AS date_id
	FROM entity) t2
	) 
GROUP BY data.id
HAVING Count(cal.id)> 1 

выборка все сущностей у которых пересекаются периоды:)
запрос мягко говоря не оптимизирован :) но можно достаточно легко оптмизировать )
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37443505
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Озверин,

не..надо было мне лучше думать ) неправильно выше) сегодня я какую то ахинею пишу
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37443656
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Озверин,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
CREATE OR REPLACE VIEW data AS 
	SELECT * 
	FROM 	(
		SELECT id, begin_date_id AS mdate
		FROM entity
		UNION ALL
		SELECT id, end_date_id AS mdate
		FROM entity) AS t1;

CREATE OR REPLACE VIEW data1 AS 
	SELECT t3.id, t3.cid, t3.cdata
	FROM (	SELECT t2.id, c.id AS cid, c.data as cdata
		FROM calendar c, data t2
		WHERE c.id >= (SELECT MIN(mdate) FROM data WHERE id = t2.id) AND c.id <=(SELECT Max(mdate) FROM data WHERE id = t2.id)
		GROUP BY t2.id, c.id, c.data) AS t3
	ORDER BY t3.id, t3.cid, t3.cdata;

SELECT t1.id
FROM data1 AS t1
WHERE EXISTS (
	SELECT t2.id
	FROM data1 AS t2
	WHERE t1.id<>t2.id AND t1.cid = t2.cid)
GROUP BY t1.id

Выборка только пересекающихся сущностей.
Можно перед EXISTS NOT и тогда выборка по только Не пересекающимся будет :)
Вроде глянул - логически корректно )
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37443717
khus-2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Озверин,

Вроде да логично, но мне надо чтобы ни при каких обстоятельствах в данных не возникло пересекающихся по датам интервалов, а не выборка только пересекающихся сущностей. Я своим ответом выше только сбил с толку, сорри.
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37443722
khus-2011
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот этот вариант почти подходит
Dimitry SibiryakovНу или убрать у сущности дату окончания действия и считать, что она действует пока ей на
замену не придёт следующая. Запросы будут чуть попроще.Только у меня возможно "пробелы" в периодах действия. Ну наверное можно выкрутиться как нить, фиктивные записи сделать или еще как.
...
Рейтинг: 0 / 0
Непересекающиеся интервалы
    #37444094
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
khus-2011Вот этот вариант почти подходит
Dimitry SibiryakovНу или убрать у сущности дату окончания действия и считать, что она действует пока ей на
замену не придёт следующая. Запросы будут чуть попроще.Только у меня возможно "пробелы" в периодах действия. Ну наверное можно выкрутиться как нить, фиктивные записи сделать или еще как.

Захотелось вернуться в начало, таблица сущностей имеет уникальный ключ?
Таблица сущностей имеет вид:
id, begin_date, end_date - где id - уникальный ключ?

я в самом деле не понимаю, что вы просите, если - авторПри конкурентном доступе есть небольшая вероятность, что по интервалам это может произойти потому, что одна сессия не видит данных другой сессии до коммита - я не улавливаю суть предложения, т.е. вы намекаете, что не можете проверять не пересекаемость диапазонов во время commit`а по это причине и...и что то просите в замен?
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Непересекающиеся интервалы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]