在我的 Trips 表版本中,我将字段名称“Name”更改为“Person”,因为 Name 是保留字。我使用 DMax() 查找此人每次出发前的最近返回日期。然后 DaysHome 可以基于 prev_return 和 Departed 之间的 DateDiff() 表达式。
SELECT
sub.Person,
sub.Departed,
sub.Returned,
sub.prev_return,
DateDiff('d',sub.prev_return,sub.Departed) AS DaysHome
FROM
(
SELECT
t.Person,
t.Departed,
t.Returned,
DMax("Returned", "Trips",
"Person = '" & Person
& "' AND Returned <= "
& Format(Departed, "\#yyyy-mm-dd\#"))
AS prev_return
FROM Trips AS t
) AS sub
ORDER BY sub.Person, sub.Departed;
这是该查询的结果集。
Person Departed Returned prev_return DaysHome
Evan 1/1/2010 6/1/2010
Evan 1/1/2011 2/1/2011 6/1/2010 214
Evan 3/10/2011 4/10/2011 2/1/2011 37
Joe 2/1/2011 5/1/2011
Joe 6/1/2011 7/1/2011 5/1/2011 31
请注意,我的版本对于您所谓的“基线旅行”而言 DaysHome 为 Null。但是你说你想要零。 IMO Null 在这里更有意义,因为你不能说那个人在他第一次离开之前回家了多少天。但是,如果您确实想要零,请使用带有 DateDiff() 表达式的 Nz() 函数。
Nz(DateDiff('d',sub.prev_return,sub.Departed), 0) AS DaysHome
您还说过“我知道我需要更新查询”。不要将 DaysHome 存储在 Trips 表中;不要将其存放在任何地方。只需在需要时进行计算。如果您将其存储在任何地方,当旅行数据发生更改时,您的值可能会不同步。
编辑:您决定将派生值存储在 Trips 表中。由于您告诉我们“我正在使用 Access 2007 进行此查询”,这意味着您可以在 UPDATE 查询中使用 VBA 用户定义函数。使用下面的 GetDaysHome() 函数,您的 UPDATE 查询可以像这样简单:
UPDATE Trips
SET Trips.DaysHome = GetDaysHome([Person],[Departed]);
或者,如果您真的希望零而不是 Null 作为“基线旅行”的 DaysHome,请使用 Nz() 函数:
UPDATE Trips
SET Trips.DaysHome = Nz(GetDaysHome([Person],[Departed]), 0);
请注意,我将 Name 字段重命名为 Person,因为 Name 是保留字。
虽然您可以只使用普通 SQL(没有 UDF)来执行 UPDATE,但这种方法对我来说编写、测试和描述要快得多。
Public Function GetDaysHome(ByVal pName As String, _
ByVal pDeparture As Date) As Variant
Dim strCriteria As String
Dim varOut As Variant
Dim varPrevReturned As Variant
strCriteria = "Person = '" & pName & _
"' AND Returned <= " & _
Format(pDeparture, "\#yyyy-mm-dd\#")
varPrevReturned = DMax("Returned", "Trips", strCriteria)
If Not IsNull(varPrevReturned) Then
varOut = DateDiff("d", varPrevReturned, pDeparture)
End If
GetDaysHome = varOut
End Function