【问题标题】:Find Days Home SQL Query找天首页SQL查询
【发布时间】:2012-02-12 17:37:33
【问题描述】:

我有一个我组织中的人员参加的旅行的列表。目标是计算个人在两次旅行之间回家的时间,查看预定旅行的过去和未来。行程未按时间顺序输入。我想在表格上运行查询以填充每次旅行的 DaysHome。

Table: Trips
Name    DaysHome Departed      Returned
Evan             1/1/2011      2/1/2011
Joe              2/1/2011      5/1/2011
Evan             3/10/2011     4/10/2011
Evan             1/1/2010      6/1/2010
Joe              6/1/2011      7/1/2011

理想情况下,查询后的表格应如下所示,显然为该人输入的第一次行程时间将为 0,因为它是基线行程。

Table: Trips
Name    DaysHome Departed      Returned
Evan    180      1/1/2011      2/1/2011
Joe     0        2/1/2011      5/1/2011
Evan    30       3/10/2011     4/10/2011
Evan    0        1/1/2010      6/1/2010
Joe     30       6/1/2011      7/1/2011

非常感谢任何帮助。我知道我需要一个更新查询,我只是不知道我是否需要一个 Join 或者我是否可以做一个嵌套的 MAX 搜索。

我正在使用 Access 2007 进行此查询。

【问题讨论】:

    标签: ms-access join


    【解决方案1】:

    在我的 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
    

    【讨论】:

    • 有没有办法把它变成一个 UPDATE 以便把天家数据写回原来的表?
    • 我知道这并不理想(或良好做法),但我的办公室将表格本身用作唯一的数据来源。这意味着踢出信息的查询将没有那么有用,我现在正在尝试您的解决方案,我们是否不需要某个地方的 max 函数来确保它选择最近的返回?
    • 我在将其转换为更新查询方面失败了。感谢您迄今为止的出色帮助
    • 您可以轻松地将其转换为生成表查询。虽然这会复制 Trips 中的数据,但至少可以保证 DaysHome 与 Trips 数据快照保持一致。
    • 我想将 DaysHome 从上面的答案更新到原始表格中,有什么建议吗?
    猜你喜欢
    • 2019-05-21
    • 2013-05-14
    • 2017-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多