访问 - 在查询中创建子总计

时间:2013-06-09 10:34:44

标签: sql ms-access

我对几个表进行查询,并以以下形式获得结果:

SomeId      Input
1           2
1           5
2           3
2           1
1           2

我希望能够将Id作为第三个字段求和,所以我会得到

SomeId      Input       subTotal
1           2           2
1           5           7
2           3           3
2           1           4
1           2           9

有可能吗? 感谢

2 个答案:

答案 0 :(得分:0)

是的,它当然是可能的,但是如上所述的问题,只能通过使用Access SQL查询来实现。这两个问题是:

  1. 源数据没有顺序键值(因此无法使用<=条件的自联接<)

  2. 源数据未按SomeId排序(表明订单可能具有其他一些意义),这会使基于集合的方法更加复杂。

  3. 幸运的是,要求这样做的VBA并不太复杂:

    Sub CreateSubtotals()
    Dim cdb As DAO.Database, rst As DAO.Recordset
    Dim dct As Object  '' Dictionary
    Set dct = CreateObject("Scripting.Dictionary")  '' New Dictionary
    Set cdb = CurrentDb
    
    '' 'dct' will hold the running totals for each 'SomeId'
    Set rst = cdb.OpenRecordset( _
            "SELECT DISTINCT SomeId " & _
            "FROM qryYourOriginalQuery", _
            dbOpenSnapshot)
    Do While Not rst.EOF
        dct.Add rst!SomeId.Value, 0
        rst.MoveNext
    Loop
    rst.Close
    
    '' create new table to hold results
    cdb.Execute _
            "SELECT SomeId, Input, 0 AS subTotal " & _
            "INTO tblYourDataWithSubtotals " & _
            "FROM qryYourOriginalQuery", _
            dbFailOnError
    
    '' fill in the 'subTotal' column
    Set rst = cdb.OpenRecordset("tblYourDataWithSubtotals", dbOpenTable)
    Do While Not rst.EOF
        dct(rst!SomeId.Value) = dct(rst!SomeId.Value) + rst!Input.Value
        rst.Edit
        rst!subTotal.Value = dct(rst!SomeId.Value)
        rst.Update
        rst.MoveNext
    Loop
    rst.Close
    Set rst = Nothing
    Set dct = Nothing
    Set cdb = Nothing
    End Sub
    

答案 1 :(得分:0)

以下是其他一些想法。两者都有它们的缺点。它们都涉及使用常规查询。

第一个想法:调用VBA函数来跟踪总计。

缺点是你必须通过SomeID订购你的桌子。

此外,当函数获得不同的SomeID时,即使它是不同的查询,运行总计也只会自行重置。这意味着第一个记录上的SomeID值必须与上一个上一个查询的最后一个记录不同。

SELECT SomeTable.SomeId, SomeTable.SomeInput, MyRunningTotal([SomeID],[SomeInput]) AS SubTotal
FROM SomeTable
ORDER BY SomeTable.SomeId;

Function MyRunningTotal(SomeID As Long, SomeInput As Long) As Long
   Static LastSomeID As Long
   Static RunningTotal As Long
   If SomeID <> LastSomeID Then
      RunningTotal = 0
      LastSomeID = SomeID
   End If
   RunningTotal = RunningTotal + SomeInput
   MyRunningTotal = RunningTotal
End Function

第二个想法:使用DSum。这基本上是查询中的查询。

缺点是对于大型记录集,它可能非常慢。这是因为它必须为每条记录运行单独的查询。

此外,您必须添加一个自动增量字段(在其ID下方的示例代码中)。

SELECT SomeTable.ID, SomeTable.SomeId, SomeTable.SomeInput, 
DSum("SomeInput","SomeTable","[SomeID]=" & [SomeID] & " and [ID]<=" & [ID]) AS SubTotal
FROM SomeTable;