【问题标题】:MS Access query, how to use SQL to group single dates into weeksMS Access 查询,如何使用 SQL 将单个日期分组为周
【发布时间】:2019-12-04 07:43:44
【问题描述】:

我目前有两张桌子。一个具有员工姓名和与该姓名关联的数字。

另一个日期有时间表日期,其中包含员工编号、日期和在该日期工作的小时数。

我想创建一个交叉表查询,在一列中显示员工姓名,每列中显示一周结束的日期,然后显示特定员工该周的小时总和。

我当前的查询有效,但只能按月分组。我很难弄清楚如何将天分组为几周。

TRANSFORM Sum(tblTimeSheetData.WorkHours) AS SumOfHours
SELECT tblEmployees.Combined
FROM tblTimeSheetData RIGHT JOIN tblEmployees ON tblTimeSheetData.EmployeeID = 
tblEmployees.EmployeeID
GROUP BY tblEmployees.Combined
ORDER BY tblEmployees.Combined, Format([WorkDate],"yyyy-mm")
PIVOT Format([WorkDate],"yyyy-mm");

【问题讨论】:

    标签: sql ms-access ms-access-2016


    【解决方案1】:

    由于第一周和最后一周的数字跨越日历年,因此必须同时包括年份和周数:

    Option Compare Database
    Option Explicit
    
        Public Const MaxWeekValue           As Integer = 53
        Public Const MinWeekValue           As Integer = 1
        Public Const MaxMonthValue          As Integer = 12
        Public Const MinMonthValue          As Integer = 1
    
    ' Returns, for a date value, a formatted string expression with
    ' year and weeknumber according to ISO-8601.
    ' Optionally, a W is used as separator between the year and week parts.
    '
    ' Typical usage:
    '
    '   FormatWeekIso8601(Date)
    '   ->  2017-23
    '
    '   FormatWeekIso8601(Date, True)
    '   ->  2017W23
    '
    ' 2017-04-28. Gustav Brock, Cactus Data ApS, CPH.
    '
    Public Function FormatWeekIso8601( _
        ByVal Expression As Variant, _
        Optional ByVal WeekSeparator As Boolean) _
        As String
    
        Const Iso8601Separator  As String = "W"
        Const NeutralSeparator  As String = "-"
    
        Dim Result              As String
    
        Dim IsoYear As Integer
        Dim IsoWeek As Integer
    
        If IsDate(Expression) Then
            IsoWeek = Week(DateValue(Expression), IsoYear)
            Result = _
                VBA.Format(IsoYear, String(3, "0")) & _
                IIf(WeekSeparator, Iso8601Separator, NeutralSeparator) & _
                VBA.Format(IsoWeek, String(2, "0"))
        End If
    
        FormatWeekIso8601 = Result
    
    End Function
    
    ' Returns the ISO 8601 week of a date.
    ' The related ISO year is returned by ref.
    '
    ' 2016-01-06. Gustav Brock, Cactus Data ApS, CPH.
    '
    Public Function Week( _
        ByVal Date1 As Date, _
        Optional ByRef IsoYear As Integer) _
        As Integer
    
        Dim Month       As Integer
        Dim Interval    As String
        Dim Result      As Integer
    
        Interval = "ww"
    
        Month = VBA.Month(Date1)
        ' Initially, set the ISO year to the calendar year.
        IsoYear = VBA.Year(Date1)
    
        Result = DatePart(Interval, Date1, vbMonday, vbFirstFourDays)
        If Result = MaxWeekValue Then
            If DatePart(Interval, DateAdd(Interval, 1, Date1), vbMonday, vbFirstFourDays) = MinWeekValue Then
                ' OK. The next week is the first week of the following year.
            Else
                ' This is really the first week of the next ISO year.
                ' Correct for DatePart bug.
                Result = MinWeekValue
            End If
        End If
    
        ' Adjust year where week number belongs to next or previous year.
        If Month = MinMonthValue Then
            If Result >= MaxWeekValue - 1 Then
                ' This is an early date of January belonging to the last week of the previous ISO year.
                IsoYear = IsoYear - 1
            End If
        ElseIf Month = MaxMonthValue Then
            If Result = MinWeekValue Then
                ' This is a late date of December belonging to the first week of the next ISO year.
                IsoYear = IsoYear + 1
            End If
        End If
    
        ' IsoYear is returned by reference.
        Week = Result
    
    End Function
    
    

    如果您只想以最后一周的日期为中心,您可以使用以下表达式:

    DateAdd("d", 7 - Weekday([WorkDate], vbMonday), [WorkDate])
    

    这假定 ISO 周编号,其中星期一是一周的第一天。

    【讨论】:

    • 语法高亮再次被破坏。这次似乎语言自动检测失败了。我看到您仍然对代码使用缩进而不是代码围栏。你知道~~~vbaon top 和~~~at bottom 做同样的事情,而且省力(特别是在语言选择上)。
    • @ComputerVersteher:已更正。我不知道。谢谢。
    【解决方案2】:

    您可以尝试使用 datepart 函数获取星期,例如

    SELECT DATEPART(ww, 'your date') AS week;
    

    然后按周分组。

    这里有更多信息 https://www.w3schools.com/sql/func_sqlserver_datepart.asp

    【讨论】:

    • MS Access' DatePart 与 SQL Server 的 DatePart 不同,前者需要一个字符串作为第一个参数,'ww'
    • 并且一年的第一周和一周的第一天有地区差异。这是 2 个可能需要调整的可选参数。向 OP 询问他的需求。但是在解决了这个问题和 Parfaits 的评论之后,你会得到我的投票;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多