我有一个包含两列beginrange和endrange的表.不应该允许重叠范围.这些列上有索引,我们尝试过很多sql条件,比如
inputBegin between beginRange and endRange or
inputEnd between beginRange and endRange
不(inputEnd< beginRange或inputStart> endRange)
等等
哪个工作正常,除非它们非常慢,因为表包含超过5mil的记录.
反正有没有写一个高效的重叠检查?
编辑:
我想到了另外一个解决方案,只有当count()在带有索引的NOT NULL列上完成时,oracle才会计算索引.如果beginRange和endRange是NOT NULL并且两者都有索引,我们可以有三个总和:
count(endRange) where inputBegin > endRange
+
count(beginRange) where inputEnd < beginRange
=
count(beginRange/endRange)
因此,对于UNION ALL,我会得到三行,在代码中我需要检查前两个的总和是否等于第三个.当然我假设只计算索引,不会访问任何行.还有其他方法吗?
最佳答案 我不确定你是否愿意:
>检查您要插入的行是否与某些现有行重叠,或者
>搜索所有现有行并识别重叠的行?
如果(1),那么你基本上已经在做什么了……
SELECT *
FROM YOUR_TABLE
WHERE :inputEnd > beginRange AND :inputStart < endRange;
…会给你重叠并且应该非常高效,前提是你有一个复合索引,其组件方向相反:{beginRange ASC,endRange DESC}.
如果(2),那么你可以像这样使用窗口:
SELECT *
FROM (
SELECT
YOUR_TABLE.*,
LEAD(beginRange) OVER (ORDER BY beginRange) nextBeginRange
FROM YOUR_TABLE
)
WHERE endRange > nextBeginRange;
这将为您提供与其下一个范围重叠的每个范围(其中“next”的含义在beginRange排序的上下文中定义).
严格来说,这甚至不需要复合索引(除非你想要covering) – 只需{beginRange}上的一个简单索引即可确保良好的性能.