如何将日期分组为周?

Posted

技术标签:

【中文标题】如何将日期分组为周?【英文标题】:How to group dates into weeks? 【发布时间】:2021-06-03 21:35:31 【问题描述】:

我有下表:

我不知何故设法编写了一个查询,该查询允许我对动物园每天的游客总数(如表格)进行汇总和分组,但我需要进一步分组为几周,以计算增长的百分比过去 4 周数据中每周的访问者数量。

如何在 Access SQL 中做到这一点?

这是查询:

SELECT TOP 35 date_info.calendar_date, Sum(restaurants_visitors.reserve_visitors) AS SUMreserve_visitors
FROM date_info INNER JOIN restaurants_visitors ON date_info.calendar_date = restaurants_visitors.visit_date
GROUP BY date_info.calendar_date
ORDER BY date_info.calendar_date DESC;

【问题讨论】:

【参考方案1】:

Access 将日期存储为浮点数,其整数部分表示自 1900 年以来的天数,其小数部分是表示为一天的小数部分的时间。如果我将日期除以 7 并截断为整数,我将有一个从周六到周五的周数。把它放在 Group By 中就可以了。

Group By Fix(date_info.calendar_date/7)

【讨论】:

【参考方案2】:

首先,您需要一个函数来计算周数。还有周数,因为周数可以跨越新年。

你可以像2021W23这样的格式来有序地列出:

' 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 WSeparator 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(WSeparator, 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

    Const MaxMonthValue          As Integer = 12
    Const MinMonthValue          As Integer = 1
    Const MaxWeekValue           As Integer = 53
    Const MinWeekValue           As Integer = 1

    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

现在您可以创建这样的查询来列出上周和 4 周前的访问者数量:

SELECT 
    FormatWeekIso8601(date_info.calendar_date) As Year_Week, 
    Sum(restaurants_visitors.reserve_visitors) AS SUMreserve_visitors
FROM 
    date_info 
INNER JOIN 
    restaurants_visitors 
    ON date_info.calendar_date = restaurants_visitors.visit_date
GROUP BY 
    FormatWeekIso8601(date_info.calendar_date)
HAVING
    FormatWeekIso8601(date_info.calendar_date) Between 
        FormatWeekIso8601(DateAdd("ww", -4, date_info.calendar_date)) And
        FormatWeekIso8601(DateAdd("ww", -1, date_info.calendar_date))
ORDER BY 
    FormatWeekIso8601(date_info.calendar_date) DESC;

来源:VBA.Date

【讨论】:

以上是关于如何将日期分组为周?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MongoDB 中按日期分组

如何在 Jooq 中按月和年将毫秒翻译成日期和分组?

如何在 React Native 中按日期分组

如何根据从 objectId 中提取的创建日期对 MongoDB 集合进行分组?

如何根据从 objectId 中提取的创建日期对 MongoDB 集合进行分组?

VBA 将日期转换为周数