我正在使用现有的表来存储开始日期,结束日期和用于排序的整数。
对于特定的开始&结束日期,我需要能够确定具有重叠日期范围的条目的最小可用整数。
例如,我的表可能存储这些记录:
7月8日 - > 7月9日订货指数为0。
7月9日 - > 7月10日,订购指数为1。
7月9日 - > 7月11日订货指数为2.
然后,给定日期范围 7月10日 - > 7月11日,我想将排序索引设置为 0 。
它需要在输入日期范围内没有其他条目的情况下工作(因此它可以默认为0)。日期范围并不总是相隔两个日期,订购索引没有限制。
我所拥有的只返回最大订单索引之上的一个:
SELECT ISNULL(MAX(order_index),-1) + 1 FROM table
WHERE start_date <= @end AND end_date >= @start)
我尝试使用this answer,但无法获得所需的结果。
答案 0 :(得分:1)
这样的事情怎么样?
declare @SampleData table ([BeginDate] date, [EndDate] date, [Order] int);
insert @SampleData values
('2015-07-08', '2015-07-09', 0),
('2015-07-09', '2015-07-10', 1),
('2015-07-09', '2015-07-11', 2);
declare @Start date = '2015-07-10';
declare @End date = '2015-07-11';
with [OrderingCTE] as
(
select
[Order],
[Ideal Order] = row_number() over (order by [Order]) - 1
from
@SampleData
where
[BeginDate] <= @End and
[EndDate] >= @Start
)
select coalesce
(
min(case [Order] when [Ideal Order] then null else [Ideal Order] end),
max([Order]) + 1
)
from
[OrderingCTE];
CTE为源表中的每条记录生成两个排序:[Order]
是存储在记录中的实际值,而[Ideal Order]
是 的值。所有可能的排序(从零开始)都在给定的日期范围内使用。
如果[Ideal Order]
在任何时候与[Order]
不同,您可以推断当前[Ideal Order]
值尚未使用,因此是最小可用值。如果在任何时候都不是这样,那么最小可用值比目前使用的最大值大1;这是脚本底部COALESCE
的后半部分。
最后请注意:您链接的问题another answer引发了对可能出现的竞争条件的担忧,具体取决于您尝试使用以这种方式查询的数据的方式。如果你还没有这样做,我强烈建议你去看看。
答案 1 :(得分:0)
我认为你可以通过枚举值来做到这一点。如果我假设订单索引没有重复,那么你可以使用row_number()
和一些算术来找到&#34; hole&#34;。需要额外的逻辑来处理边缘情况。
with t as (
select t.*,
row_number() over (order by order_index) as seqnum,
min(order_index) over () as minoi,
max(order_index) over () as maxoi
from table t
where start_date <= @end and end_date >= @start
)
select (case when min(minoi) > 0 then 0
when min(minoi) is null then min(maxoi + 1)
else min(minoi + seqnum - 1)
end)
from t
where order_index <> minoi + seqnum - 1 or
order_index = maxoi
答案 2 :(得分:0)
我会尝试这样的事情:
SELECT
COALESCE(
MIN(CASE WHEN t2.order_index IS NULL THEN t1.order_index - 1 ELSE NULL END),
MAX(t1.order_index) + 1,
0)
FROM TheTable t1
LEFT JOIN TheTable t2
ON t2.order_index = t1.order_index - 1
AND t2.start_date <= @end
AND t2.end_date >= @start
WHERE t1.start_date <= @end
AND t1.end_date >= @start