Здравствуйте, 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
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 даже?
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)
)
);
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.
Здравствуйте, merge, Вы писали:
M>В базе mssql есть таблица
M>contracts M> country M> period start M> period end
M>как можно создать уникальный индекс на страну и чтобы не было пересечения дат для одной страны? M>триггер знаю, но вот хотелось бы индексом
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, merge, Вы писали:
M>>В базе mssql есть таблица
M>>contracts M>> country M>> period start M>> period end
M>>как можно создать уникальный индекс на страну и чтобы не было пересечения дат для одной страны? M>>триггер знаю, но вот хотелось бы индексом
G>Но даже если поциента нельзя вылечить, это не значит что ему нельзя помочь. G>Для ускорения поиска пересечения интервалов существует подход, называемый Relational Interval Tree.
да, но почему для таких, по идее, частых задач нет встроенных средств кроме триггера?
я так понимаю чтобы такое реализовать надо триггер тот же делать на уровне базы
Здравствуйте, 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.