【问题标题】:MS Access complex grouping and sumMS Access 复杂分组和求和
【发布时间】:2013-06-12 14:26:51
【问题描述】:

我似乎遇到了一个难以访问的问题。我的数据如下表所示,每个人都有一个开始和结束日期以及两者之间的天数。我要做的是将所有连续的作业长度加在一起,这意味着一个的结束日期是下一个开始日期的前一天。在下面的示例中,我想对记录 1,2,3 的分配长度求和,并分别求和 4,5,因为结束日期和开始日期之间存在中断。它处于访问状态,因此我可以使用查询或 vba 来完成,我不确定这里的最佳解决方案是什么。
ID Name StartDate EndDate AssignmentLength
1 -- 鲍勃 -- 2013 年 1 月 1 日 -- 2013 年 2 月 1 日 -- 30
2 -- 鲍勃 -- 2013 年 2 月 2 日 -- 2013 年 3 月 1 日 -- 30
3 -- 鲍勃 -- 2013 年 3 月 2 日 -- 2013 年 4 月 1 日 -- 30
4 -- 鲍勃 -- 2013 年 5 月 1 日 -- 2013 年 6 月 1 日 -- 30
5 -- 鲍勃 -- 2013 年 6 月 2 日 -- 2013 年 7 月 1 日 -- 30

【问题讨论】:

    标签: sql ms-access


    【解决方案1】:

    我在给定数据中添加了一条附加记录:

    periodID    fname   startdate   enddate
    6           bob     8/1/2013    9/1/2013
    

    有一个不跨越记录的时期。我将表格命名为工作周期。

    通过修改后的数据,我们可以发现工期开始于:

    SELECT *
    FROM workperiods
    WHERE periodid NOT IN
        (SELECT a.periodid
         FROM workperiods a
         INNER JOIN workperiods b ON a.startdate =b.enddate+1);
    

    我们可以找到工作时间以

    结尾
    SELECT *
    FROM workperiods
    WHERE periodid NOT IN
        ( SELECT a.periodid
         FROM workperiods a
         INNER JOIN workperiods b ON a.enddate =b.startdate-1);
    

    然后我们可以构建这个怪物:

    SELECT startdate,
           enddate,
           enddate-startdate AS periodlength
    FROM
      (SELECT startdate,
              min(enddate) AS enddate
       FROM
         (SELECT c.startdate,
                 f.enddate
          FROM
            (SELECT *
             FROM workperiods
             WHERE periodid NOT IN
                 (SELECT a.periodid
                  FROM workperiods a
                  INNER JOIN workperiods b ON a.startdate =b.enddate+1)) AS c,
    
            (SELECT *
             FROM workperiods
             WHERE periodid NOT IN
                 (SELECT d.periodid
                  FROM workperiods d
                  INNER JOIN workperiods e ON d.enddate =e.startdate-1)) AS f
          WHERE f.startdate >c.enddate
            OR c.startdate=f.startdate)
       GROUP BY startdate)
    

    这给出了:

    startdate   enddate     periodlength
    1/1/2013    4/1/2013    90
    5/1/2013    7/1/2013    61
    8/1/2013    9/1/2013    31
    

    这可能是想要的结果。

    它不漂亮,但我认为它到达那里。

    【讨论】:

    • +1 用于完成提出 SQL 解决方案的练习。有时它们看起来有点吓人,但作为一个谜题,它们比启动 VBA 和循环遍历记录集更有趣。 ;)
    • 最终结果正是我想要的,希望它有效,我会告诉你的。
    • @GordThompson 感谢您的客气话。它看起来可以用直接的 SQL 完成,所以我想尝试一下。
    • 干得好。严格的 SQL 解决方案通常比使用 VBA 更可取。为了便于阅读,我对您的 SQL 进行了一些格式化。 +1。
    • 这很好用,当我最初发布时我没有考虑到一些事情,我花了一些时间来围绕它进行我需要的更改,但最终这帮助我实现了正确的解决方案。谢谢
    【解决方案2】:

    我会使用 VBA 和 DateDiff()。然后你可以循环遍历每个并比较以查看总数是否小于 1。

    【讨论】:

      【解决方案3】:

      也许你可以从中得到一些想法。可以针对月份的实际长度修改 AssignmentLength。如果您有一些想法,请标记为已回答。

      Sub dates()
      Dim cn As ADODB.Connection
      Dim rs As ADODB.Recordset
      Dim ConnStr As String
      ''Dim below arrays
      Set cn = New ADODB.Connection
      ConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
          "C:\Users\Philosophaie\Documents\a  access\a Chase.mdb;"
      cn.Open ConnStr
      Set rs = New ADODB.Recordset
      rs.Open Source:="Checking", ActiveConnection:=cn, _
          CursorType:=adOpenKeyset, LockType:=adLockOptimistic, _
          Options:=adCmdTableDirect
      rs.MoveFirst
      Do Until rs.EOF
         If rs!Name = "bob" Then
             n=n+1
             datestart(n)=rs!StartDate
             dateend(n)=rs!EndDate
             assignmentlength(n)=rs!AssignmentLength
          End If
          rs.MoveNext
      Loop
      for i=1 to n
          mostart(i)=Left(datestart(i),1)
          dystart(i)=right(left(datestart,3),1)
          yrstart(i)=right(datestart,4)
      ''do the same for end
      next I
      for i=1 to n
          if moend(I)=mostart(i) then
              if dyend(I)=daystart(I)+1 then
                 if yrend(I)=yrstart(I) then
                    aslen(j)=assignmentlength(I)+aslen(j)
                 else
                    j=j+1
                 end if
              else
                    j=j+1
              end if
          else
              j=j+1
          end if
        next I
      ''output
      End sub
      

      【讨论】:

        猜你喜欢
        • 2021-10-13
        • 1970-01-01
        • 2023-03-28
        • 2020-04-06
        • 1970-01-01
        • 2023-03-25
        • 2020-08-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多