检查日期是否在未指定年份的期间内下降

时间:2013-08-01 13:39:56

标签: sql sql-server database-design access-vba inventory-management

我有一个表格,它只使用月和日来定义几个不重叠的日期。它基本上是库存物品的“库存”表,允许您在季节性业务中全年存储不同的金额。以下是单个商品库存表的外观示例。请注意,我有一个项目表,我没有在这里显示。在下表中,ItemID是外键,StockID是主键。

StockID    ItemID    BeginDate    EndDate    QtyTrigger    ReorderQty
      1         1         11/1       1/31             0             1
      2         1          2/1       5/31             1             2
      3         1          6/1      10/31             1             1

所以,假设我想获得2013年1月15日的重新排序查询/报告。使用我当前的逻辑,我的查询将返回错误,因为它看起来像这样:

SELECT i.*, st.QtyTrigger, st.ReorderQty
FROM t20Itm AS i INNER JOIN t20Itm_Stock AS st ON i.ItemID = st.ItemID
WHERE #01/14/2013# >= CDate(st.BeginDate & "/2013" ) AND
#01/14/2013# <= CDate(st.EndDate & "/2013")
AND i.QtyOnHand <= st.QtyTrigger

问题是此示例中的11/1的BeginDate需要是11/1/2012。在我的示例中,我正在展示2013年,因为这是我能够用来生成此查询的唯一逻辑。

我怀疑我的问题可能是一个更大的设计缺陷,所以我正在寻找一个如何实现这一目标的答案,或者更好的想法,也许有一些原因可能是为什么这个设计是一个坏主意。

我知道我可以通过不允许12月31日的日期跨度来实现这一目标。但是,该应用程序的许多用户的时间段从11月到2月是他们最慢的月份。他们最终将创建两个不同的日期跨度,其中包含相同的数据,一个用于11月/ 12月,另一个用于1月/ 2月。

我正在使用SQL Server作为数据库,MS Access用于前端应用程序。我可以使用T-SQL或Access VBA,因此您的解决方案可以在任何一个。

1 个答案:

答案 0 :(得分:1)

我相信这个肮脏的where-clause-hack应该这样做:

WHERE 
  ((CDate(st.BeginDate & "/2013" ) <= (CDate(st.EndDate & "/2013" )) 
    AND (#01/14/2013# BETWEEN CDate(st.BeginDate & "/2013" ) AND CDate(st.EndDate & "/2013")))
  OR
  ((CDate(st.BeginDate & "/2013" ) > (CDate(st.EndDate & "/2013" )) 
    AND (#01/14/2013# BETWEEN CDate(st.BeginDate & "/2012" ) AND CDate(st.EndDate & "/2013")))

注意这两个OR表达式在年份(2013年与2012年)不同。如果begin-end按时间顺序排列,则使用第一个表达式(同年)。如果没有,则使用第二个表达式(从去年开始,以当前结束)。

然而,这可能会有非常糟糕的表现。我建议您将日期存储为两个单独的列,并使用此或类似的逻辑进行查询。只有这样你才能利用索引。