Уникальный индекс на диапазон дат
От: merge  
Дата: 05.11.24 07:30
Оценка:
В базе mssql есть таблица

contracts
country
period start
period end

как можно создать уникальный индекс на страну и чтобы не было пересечения дат для одной страны?
триггер знаю, но вот хотелось бы индексом
Re: Уникальный индекс на диапазон дат
От: BlackEric http://black-eric.lj.ru
Дата: 07.11.24 08:19
Оценка:
Здравствуйте, merge, Вы писали:

M>В базе mssql есть таблица


M>contracts

M> country
M> period start
M> period end

M>как можно создать уникальный индекс на страну и чтобы не было пересечения дат для одной страны?

M>триггер знаю, но вот хотелось бы индексом

USE AdventureWorks2017;
GO

DROP INDEX IF EXISTS FIBillOfMaterialsWithEndDate
    ON Production.BillOfMaterials
GO

CREATE NONCLUSTERED INDEX FIBillOfMaterialsWithEndDate
    ON Production.BillOfMaterials (ComponentID, StartDate)
    WHERE EndDate IS NOT NULL and EndDate > '2022-01-01';
GO
https://github.com/BlackEric001
Re[2]: Уникальный индекс на диапазон дат
От: merge  
Дата: 07.11.24 15:44
Оценка:
Здравствуйте, BlackEric, Вы писали:


BE>CREATE NONCLUSTERED INDEX FIBillOfMaterialsWithEndDate

BE> ON Production.BillOfMaterials (ComponentID, StartDate)
BE> WHERE EndDate IS NOT NULL and EndDate > '2022-01-01';
BE>GO
BE>[/sql]

так а как он поможет если вставлять просто другую StartDate даже?


insert BillOfMaterials (1, 01-01-2023, 04-04-2023)

insert BillOfMaterials (1, 03-03-2023, 06-06-2023)


такого не должно быть
Re[3]: Уникальный индекс на диапазон дат
От: BlackEric http://black-eric.lj.ru
Дата: 07.11.24 19:32
Оценка:
Здравствуйте, merge, Вы писали:

CREATE UNIQUE INDEX UQ_Contracts_Country_Period 
ON contracts (country, period_start, period_end)
WHERE NOT EXISTS (
    SELECT 1 
    FROM contracts AS c
    WHERE c.country = contracts.country
    AND (
        (contracts.period_start < c.period_end AND contracts.period_end > c.period_start)
    )
);
https://github.com/BlackEric001
Re[4]: Уникальный индекс на диапазон дат
От: merge  
Дата: 08.11.24 06:57
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, merge, Вы писали:


BE>
BE>CREATE UNIQUE INDEX UQ_Contracts_Country_Period 
BE>ON contracts (country, period_start, period_end)
BE>WHERE NOT EXISTS (
BE>    SELECT 1 
BE>    FROM contracts AS c
BE>    WHERE c.country = contracts.country
BE>    AND (
BE>        (contracts.period_start < c.period_end AND contracts.period_end > c.period_start)
BE>    )
BE>);
BE>



кхм, у меня ошибка на такой конструкции "incorrect where clause for filtered index"
ругается на WHERE NOT EXISTS

у вас создается такой индекс на таблице?
какая версия скл?
Re[5]: Уникальный индекс на диапазон дат
От: BlackEric http://black-eric.lj.ru
Дата: 08.11.24 15:05
Оценка:
Здравствуйте, merge, Вы писали:

Нет, делайте через триггер.
Нейросети врут.
https://github.com/BlackEric001
Re[5]: Уникальный индекс на диапазон дат
От: paucity  
Дата: 08.11.24 15:19
Оценка:
Здравствуйте, merge, Вы писали:


M>кхм, у меня ошибка на такой конструкции "incorrect where clause for filtered index"


Возможно это:

Filtered indexes are defined on one table and only support simple comparison operators.


Имхо, "NOT EXISTS (SELECT ...) выходит за рамки simple comparison operators.

Или помнится, при сравнении datetime помогало конвертировать в date, тогда вот это:

If the comparison operator specified in the filtered index expression of the filtered index results in an implicit or explicit data conversion, an error will occur if the conversion occurs on the left side of a comparison operator. A solution is to write the filtered index expression with the data conversion operator (CAST or CONVERT) on the right side of the comparison operator.

Re[6]: Уникальный индекс на диапазон дат
От: merge  
Дата: 08.11.24 17:41
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, merge, Вы писали:


BE>Нет, делайте через триггер.

BE>Нейросети врут.

chatGpt?
Re[7]: Уникальный индекс на диапазон дат
От: BlackEric http://black-eric.lj.ru
Дата: 09.11.24 16:14
Оценка:
Здравствуйте, merge, Вы писали:

M>chatGpt?


https://www.perplexity.ai/
https://github.com/BlackEric001
Re: Уникальный индекс на диапазон дат
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.11.24 15:21
Оценка: 158 (4)
Здравствуйте, merge, Вы писали:

M>В базе mssql есть таблица


M>contracts

M> country
M> period start
M> period end

M>как можно создать уникальный индекс на страну и чтобы не было пересечения дат для одной страны?

M>триггер знаю, но вот хотелось бы индексом

Но даже если поциента нельзя вылечить, это не значит что ему нельзя помочь.
Для ускорения поиска пересечения интервалов существует подход, называемый Relational Interval Tree.
Длинная научная работа на эту тему https://www.dbs.ifi.lmu.de/research/CAD/presentations/RI-Tree.pdf
Оптимизация https://lucient.com/blog/a-static-relational-interval-tree/
Даже пример кода есть https://github.com/icomefromthenet/mysqlfastintervallookup?tab=readme-ov-file
Re[2]: Уникальный индекс на диапазон дат
От: merge  
Дата: 12.11.24 10:16
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, merge, Вы писали:


M>>В базе mssql есть таблица


M>>contracts

M>> country
M>> period start
M>> period end

M>>как можно создать уникальный индекс на страну и чтобы не было пересечения дат для одной страны?

M>>триггер знаю, но вот хотелось бы индексом

G>Но даже если поциента нельзя вылечить, это не значит что ему нельзя помочь.

G>Для ускорения поиска пересечения интервалов существует подход, называемый Relational Interval Tree.

да, но почему для таких, по идее, частых задач нет встроенных средств кроме триггера?
я так понимаю чтобы такое реализовать надо триггер тот же делать на уровне базы
Re[3]: Уникальный индекс на диапазон дат
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 12.11.24 14:57
Оценка:
Здравствуйте, merge, Вы писали:

M>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, merge, Вы писали:


M>>>В базе mssql есть таблица


M>>>contracts

M>>> country
M>>> period start
M>>> period end

M>>>как можно создать уникальный индекс на страну и чтобы не было пересечения дат для одной страны?

M>>>триггер знаю, но вот хотелось бы индексом

G>>Но даже если поциента нельзя вылечить, это не значит что ему нельзя помочь.

G>>Для ускорения поиска пересечения интервалов существует подход, называемый Relational Interval Tree.

M>да, но почему для таких, по идее, частых задач нет встроенных средств кроме триггера?

Почему же нет?
В постгре есть, довольно давно https://postgrespro.ru/docs/postgresql/17/rangetypes
Это чуть более навороченный тип, и, соотвественно, более навороченные индексы на базе GiST

M>я так понимаю чтобы такое реализовать надо триггер тот же делать на уровне базы

Проверка уникальности индекса это проверка что ключ (по сути число) не существует в дереве индекса. Я не уверен что задачу проверки пересечения интервалов можно свести к сравнению чисел на равенство, поэтому такая проверка возможна только с помощью триггера. А вот как построить индекс для ускорения запроса в таком триггере — написать функцию, что возможно на любом диалекте SQL.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.