2013-10-21 52 views
3

我一直在这个问题上砸了我三天的头现在,也许你可以帮助我在这一个。比较日期范围与建立查询时的具体日期

所以,我有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之间获得/ 2012和2014年1月1日)

回答

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 

如果您保存在访问该查询,那么你可以使用它(就像你使用一个表)在其他查询执行其余的部分 的计算。

+0

感谢您的回答。 如果我理解的很好,如果在这个月没有价格变化,这个函数会给出正常的价格,或者如果它发生的话,按比例计算。 所以,如果我想用我的公式来执行我计算我只需要做到以下几点: 'SELECT SUM((AverageMonthlyPrice(Sales.ItemName,Sales.SaleMonth)* Sales.Number)/ EXCHANGERATE。价格)AS收益 从销售,[汇率] WHERE Sales.Itemname =“Watch” AND Sales.SaleMonth BETWEEN DATEADD(“m”,-1,01/02/2012)和DATEADD(“m”, - 1,31/12/2013) AND [Exchangerate] .Exchangemonth = DATEADD(“m”,1,Sales.SaleMonth);' 对吗? – Tom

+0

@Tom是的,如果该月没有价格变化,函数应该给出“正常”的价格。至于你的查询,为什么不试着对付你的一小部分数据,看你的结果与你自己“做数学”时得到的结果是否相符? –

+0

我将它标记为很好的答案,因为我认为这是我要这样做的方式,但我只有一个问题。这只是我的问题的一个简单例子,我的表比较复杂一些,例如Sales.Itemname不等于[Item price] .Itemname,但两个表由另一个链接。你的函数中要修改哪些字段来匹配具有不同字段的表,但基本上这些字段包含相同的数据? – Tom