使用两个不同的日期选择顶行

时间:2013-05-01 14:53:58

标签: sql

表格包含PriceValidFrom,PriceValidTo,BookingWindowFrom和BookingWindowTo日期字段以及价格货币字段。客户端随机插入或更新行。例如,某些行的PriceValid时间段可能比其他行短,但可能在同一个月内(并且具有不同的价格)。其他行可能具有相同的PriceValid期间,但可能仅在BookingWindow期间有所不同。桌子永远不会被清理,一切都是可以接受的。 我需要一个查询,给定一个日期,将从具有最高PriceValidFrom日期的行返回价格。在下面的示例中,考虑表和查询语句:

PriceValidFrom PriceValidTo Price
05/01/2013     05/30/2013   $100.00
05/15/2013     05/20/2013   $50.00

伪sql

select top 1 price
where :Date between PriceValidFrom and PriceValidTo   
order by PriceValidFrom DESC, Price

如果日期是05/16/2013,则查询会按预期返回$ 50.00。

现在,用户需要添加一个必须采用最高BookingWindowFrom的预订窗口期间:

PriceValidFrom PriceValidTo Price     BookingWindowFrom  BookingWindowTo
05/01/2013     05/30/2013   $100.00   4/1/2013           5/30/2013 
05/15/2013     05/20/2013   $50.00    4/1/2013           5/30/2013
05/15/2013     05/20/2013   $75.00    5/1/2013           5/30/2013

现在,如果日期是05/16/2013且预订日期是5/1/2013,则查询需要返回$ 75.00

如何达到预期效果?请注意,这是一个简化的示例,但实际表中将有数百行。

select top 1 price 
where :Date between PriceValidFrom and PriceValidTo    
    and  :BookingDate  between BookingWindowFrom  and  BookingWindowTo

2 个答案:

答案 0 :(得分:1)

ORDER BY不是解决方案,您必须更改WHERE子句。例如:

SELECT top 1 price     
WHERE EffectiveDate = :pDate
   OR (EffectiveDate IS NULL AND :pDate BETWEEN ValidFrom AND ValidTo)

ORDER BY EffectiveDate DESC, ValidFrom DESC, Price

我在这里假设有关你的架构的一些事情,但我认为这应该可以帮助你开始。

答案 1 :(得分:1)

这是基于我想要使用EffectiveDate的想法的猜测:

select top 1 price
where :pDate between coalesce(EffectiveDate, ValidFrom) and ValidTo
order by coalesce(EffectiveDate, ValidFrom) DESC, Price

或者,如果有可用的有效日期,您是否想简单地抛弃所有的ValidXXX日期?

我通常建议使用min / max或ranking函数来获取价格,而不是巧妙地使用order子句操纵非ANSI top,但这只是一个意见。

我必须承认,这个EffectiveDate乍一看似乎有些迟钝,无法正确清理ValidFrom / To日期,例如“我们不想花时间纠正我们的数据,只是让这个价格现在正好!“因此,什么阻止EffectiveDates变得过多,使您看起来需要添加ReallyEffectiveDate列? “有效”和“有效”这两个词在这里看起来像是同义词,对于理解和编程可能会非常混乱。好的,充满假设的咆哮。