在Access查询中使用开始日期和结束日期

时间:2012-02-15 15:23:24

标签: sql ms-access

有人可以帮助我解决我想要创建的Access查询吗?

我有一个包含项目列表及其开始日期和结束日期的表格。我需要的是一个查询,显示每个项目的逐月项目细分,例如:

PROJECT    Jan       Feb       Mar
AAAAA       7        28        2

...等,其中数字是根据开始日期和结束日期计算的项目天数。例如,在上述查询中,项目AAAAA的开始日期为24/01/2012,结束日期为02/03/2012

有人可以指导我如何实现这个目标吗?

非常感谢!!

2 个答案:

答案 0 :(得分:1)

我创建了一个日历表,以便更容易应对。我在下面包含了我使用的两个过程(CreateTable_calendar和LoadCalendar)的代码。我在日历表中添加了“work_day”字段,以防您将天数限制为仅在每个月的组织工作日。如果是这样,您将需要相应地调整查询的WHERE子句。如果我的选择与您的选择不匹配,还会重置每个日历日期的work_day值。

无论如何,我会留下这些细节供你整理。如果不对工作日和非工作日进行调整,此查询将返回我认为您想要的结果集。

TRANSFORM Count(sub.the_date) AS CountOfProjectDays
SELECT sub.Project_name
FROM
    (
        SELECT
            p.Project_name,
            MonthName(Month(c.the_date),-1) AS month_name,
            c.the_date
        FROM Projects AS p, tblCalendar AS c
        WHERE
            c.the_date >= [p].[start_date]
            And c.the_date <= [p].[end_date]
        ORDER BY p.Project_name
    ) AS sub
GROUP BY sub.Project_name
PIVOT sub.month_name
    In ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
       "Aug", "Sep", "Oct", "Nov", "Dec");

备注

  1. 我使用了PIVOT之后的月份名称列表来强制列的顺序。如果没有该列表,列将按月名称的字母顺序显示。如果您不想/需要所有12个月的列,请缩短该列表。
  2. 当所有日期都来自一个日历年时,此方法应该有效。如果你想处理超过一年的日期范围......你还有更多工作要做。 : - )
  3. 制作日历表:

    Public Sub CreateTable_calendar()
        Const cstrTable As String = "tblCalendar"
        Dim cn As Object
        Dim strSql As String
        Set cn = CurrentProject.Connection
    
        On Error Resume Next
        cn.Execute "DROP TABLE " & cstrTable & ";"
        If Err.Number <> 0 Then
            Debug.Print Err.Description
        End If
        On Error GoTo 0
    
        strSql = "CREATE TABLE " & cstrTable & " (" & vbCrLf & _
            "the_date DATETIME CONSTRAINT pkey PRIMARY KEY," & vbCrLf & _
            "work_day YESNO," & vbCrLf & _
            "CONSTRAINT midnite_only CHECK " & _
            "(the_date = DateValue(the_date))" & vbCrLf & _
            ");"
        Debug.Print strSql
        cn.Execute strSql
    
        Set cn = Nothing
    End Sub
    

    加载日历表。如果不给它一年的论据,它将加载当年的所有日期。否则,它会加载您提供的年份的日期作为参数。

    Public Sub LoadCalendar(Optional ByVal pYear As Integer)
        Const cstrTable As String = "tblCalendar"
        Dim db As DAO.Database
        Dim dte As Date
        Dim intYear As Integer
        Dim rs As DAO.Recordset
        Dim strMsg As String
    
    On Error GoTo ErrorHandler
    
        intYear = IIf(pYear = 0, Year(Date), pYear)
        dte = DateSerial(intYear, 1, 1)
    
        Set db = CurrentDb
        Set rs = db.OpenRecordset(cstrTable, dbOpenTable, dbAppendOnly)
    
        Do While Year(dte) = intYear
            rs.AddNew
            rs!the_date = dte
            rs!work_day = Not (Weekday(dte) = vbSunday Or _
                Weekday(dte) = vbSaturday)
            rs.Update
            dte = dte + 1
        Loop
        rs.Close
    
    ExitHere:
        On Error GoTo 0
        Set rs = Nothing
        Set db = Nothing
        Exit Sub
    
    ErrorHandler:
        strMsg = "Error " & Err.Number & " (" & Err.Description _
            & ") in procedure LoadCalendar"
        MsgBox strMsg
        GoTo ExitHere
    End Sub
    

    修改:日历是保留字。见Problem names and reserved words in Access。直到我和布朗先生Database Issue Checker Utility检查我的数据库之前,我才注意到这一点。所以我在这个答案中将名称日历更改为tblCalendar。我强烈推荐这个实用程序。除了识别保留字的问题外,它还可以告知您许多其他潜在的问题。

答案 1 :(得分:0)

建议您查看交叉表查询:http://www.databasedev.co.uk/crosstab_queries.html

这显示了您正在寻找的结果类型 - 每月计数。请注意,您可能需要计算每月的天数作为临时步骤,例如,通过每月使用一个表来指定开始日期和结束日期,然后您可以计算每个项目每月使用的天数。

您的步骤如下:
1个日期范围表每月
2计算每个项目每月的开始和结束日期

Select p.projectName, md.monthNumber,
Case when p.startDate < md.startDate then md.startDate
When p.startDate < md.endDate then p.startDate else p.endDate
, case when p.endDate > md.endDate then md.endDate
When p.endDate > md.startDate then p.endDate else md.startdate end
From @projects p
Inner join @monthDates md on p.startDate <= md.endDate and p.endDate > md.startDate

在Access中,我认为IIF等同于CASE?

你需要根据你想要计算一个月的第一天/最后几天的方式来调整上面的内容(如果一个项目在31日完成它是否计入jan还是需要继续第一个feb等)但是它足以让你入门

最后,使用Access交叉表将其转换为所需格式,在每月的项目开始日期和结束日期之间进行日期减法。