在构建查询时将日期范围与特定日期进行比较

时间:2013-10-21 10:40:51

标签: sql ms-access

我已经把这个问题压了三天,现在也许你可以帮我解决这个问题。

所以,我有3张桌子。

一个名为项目价格,其中包含某些项目在给定时间内的价格。

基本上表格如下:

ItemName | Startdate  | Enddate    | Price
-------------------------------------------
Watch    | 01/01/2012 | 04/08/2012 | 180€
Watch    | 05/08/2012 | 31/12/2012 | 150€
Watch    | 01/01/2013 | 31/12/2013 | 200€

另一张表名为销售,其中包含每月销售的商品数量。

表格如下:

ItemName | SaleMonth  | Number
-----------------------------
Watch    | 01/01/2012 | 93
  .             .        .
  .             .        .
  .             .        .
Watch    | 01/05/2013 | 59
Watch    | 01/06/2013 | 74

最后一个名为汇率,每个月的汇率从欧元到英镑。

ExchangeMonth | Rate  |
-----------------------
 01/01/2013   | 1.225 | 
 01/02/2013   | 1.166 |

为了计算一个月内我获得了多少,我使用这个公式:

Gain_month_i = (ItemPrice_month_i-1 * ItemsSold_month_i-1)/ExchangeRate_month_i

我想计算在特定时期内我获得了多少。

但如果我选择的时期在我的物品价格表中的不同时期重叠,我找不到获得正确结果的方法(例如,如果我想知道我在01/02 / 02之间获得了多少收益2012年和2014年1月1日)

1 个答案:

答案 0 :(得分:1)

问题的实质是您的[销售]号码按月汇总,但物品的价格可能在月份的开始和结束之间发生变化。因此,如果您在2012年8月售出50只手表,那么当价格为180时,您不确定售出多少手表,以及在价格降至150之后售出多少手表。

在我看来,唯一合理的解决方案是使用基于各个价格生效的月份天数的平均月度价格。您可以通过使用这样的VBA函数来实现:

Option Compare Database
Option Explicit

Public Function AverageMonthlyPrice(ItemName As String, AnyDayInMonth As Date) As Variant
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Dim FirstDayOfMonth As Date, LastDayOfMonth As Date, NumDaysInMonth As Long
Dim IntervalStart As Date, IntervalEnd As Date
Dim WeightedAveragePrice As Variant

WeightedAveragePrice = Null
FirstDayOfMonth = DateSerial(year(AnyDayInMonth), Month(AnyDayInMonth), 1)
LastDayOfMonth = DateAdd("d", -1, DateSerial(year(AnyDayInMonth), Month(AnyDayInMonth) + 1, 1))
NumDaysInMonth = DateDiff("d", FirstDayOfMonth, LastDayOfMonth) + 1
Set qdf = CurrentDb.CreateQueryDef("", _
        "SELECT * FROM [Item Price] " & _
        "WHERE ItemName = [pItemName] " & _
            "AND Enddate >= [pFirstDay] AND Startdate <= [pLastDay]")
qdf!pItemName = ItemName
qdf!pFirstDay = FirstDayOfMonth
qdf!pLastDay = LastDayOfMonth
Set rst = qdf.OpenRecordset(dbOpenSnapshot)
Do While Not rst.EOF
    IntervalStart = IIf(rst!StartDate < FirstDayOfMonth, FirstDayOfMonth, rst!StartDate)
    IntervalEnd = IIf(rst!EndDate > LastDayOfMonth, LastDayOfMonth, rst!EndDate)
    WeightedAveragePrice = Nz(WeightedAveragePrice, 0) + rst!Price * (DateDiff("d", IntervalStart, IntervalEnd) + 1) / NumDaysInMonth
    rst.MoveNext
Loop
rst.Close
Set rst = Nothing
Set qdf = Nothing
If Not IsNull(WeightedAveragePrice) Then
    WeightedAveragePrice = CCur(WeightedAveragePrice)
End If
AverageMonthlyPrice = WeightedAveragePrice
End Function

现在,您可以在Access中运行查询,将[销售]表格中每行的销售数量,平均价格和汇率汇总在一起:

SELECT
    Sales.ItemName,
    Sales.SaleMonth,
    Sales.Number,
    AverageMonthlyPrice(Sales.ItemName, Sales.SaleMonth) AS AveragePrice,
    [Exchange Rate].Rate AS ExchangeRate
FROM
    Sales
    INNER JOIN
    [Exchange Rate]
        ON [Exchange Rate].ExchangeMonth = Sales.SaleMonth

...返回类似的内容:

ItemName  SaleMonth   Number  AveragePrice  ExchangeRate
--------  ----------  ------  ------------  ------------
Watch     2012-01-01      93  180                  1.225
Watch     2012-08-01      50  153.871              1.166
Watch     2013-06-01      74  200                  1.234
Watch     2013-05-01      59  200                  1.123

如果您在Access中保存该查询,那么您可以在其他查​​询中使用它(就像您使用表格一样)来执行其余的计算。