【问题标题】:Query end of week and end of month data查询周末月末数据
【发布时间】:2021-09-14 22:35:15
【问题描述】:

在 Access 数据库中,如果我有一些格式为

的股票数据
DateFormatted      DateSeconds        CodeName       Close     
2000-01-01          946684800          AAA           1.01
2000-01-02          946771200          AAA           1.02
2000-01-03          946857600          AAA           1.03
2000-01-04          946944000          AAA           1.04
2000-01-05          947030400          AAA           1.05
2000-01-08          947289600          AAA           1.06
.
.
.

并注意它从0508,以及DateFormattedShort Text,而不是Date。考虑到连续日期格式,似乎几乎不可能根据 WHERE 子句中的特定日期查询月末 (01-31)。相反,我希望由于数据库中可能不存在此类值(由于周末、公共假期、系统错误等原因),这意味着周末可能在星期四结束,一周开始可能在星期二开始,月末可能是当月最后一天的前 3 天,等等,有一种在查询中获取此类数据的已知方法。这怎么可能?

请注意,在上面的示例中,周末将是 1.05,月末(如果您继续保持每天 +0.01 的趋势)将是 1.31

【问题讨论】:

    标签: sql date ms-access


    【解决方案1】:

    如果您想要每个月的数据中的最后一行,您可以使用相关子查询:

    select s.*
    from stocks as s
    where s.date = (select max(s2.date)
                    from stocks as s2
                    where s2.code = s.code and
                          year(s2.date) = year(s.date) and
                          month(s2.date) = month(s.date)
                   );
    

    你可以用 datepart() 做类似的事情几周。

    【讨论】:

    • 效果很好,我唯一的问题是运行查询需要大约 10 多秒。我编辑了可能有助于理解原因的问题,这可能是因为很多子字符串或其他原因。但基本上,我存储Date 的方式是Short Text - 原因是将数据加载到C++ 程序中不需要从int 的Struct 转换为字符串。 - 我有CodeNameDateFormattedDateSeconds 所有索引。
    【解决方案2】:

    您希望获得的是一周/月结束日期之前的最后股票价值。因此,在每种情况下,您都需要找到该日期。在您的周末情况下,它将是:

    DateAdd("d",5-Weekday(StockDate,6),StockDate)
    

    而在月底是:

    DateSerial(Year(StockDate),Month(StockDate)+1,-1) 
    

    然后,您将在查询中使用这两个结果来获取所选日期之前的值:

    SELECT DISTINCT 
        S.StockCode, 
        DateAdd("d",5-Weekday(S.StockDate,6),S.StockDate) AS WeekEnding,
        (SELECT TOP 1 S1.StockClose FROM tblStock AS S1 WHERE S.StockCode=S1.StockCode AND S1.StockDate<=DateAdd("d",5-Weekday(S.StockDate,6),S.StockDate) ORDER BY S1.StockDate DESC) AS WeekClose
    FROM tblStock AS S
    

    SELECT DISTINCT 
        S.StockCode, 
        DateSerial(Year(S.StockDate),Month(S.StockDate)+1,-1) AS MonthEnding,
        (SELECT TOP 1 S1.StockClose FROM tblStock AS S1 WHERE S.StockCode=S1.StockCode AND S1.StockDate<=DateSerial(Year(S.StockDate),Month(S.StockDate)+1,-1) ORDER BY S1.StockDate DESC) AS MonthClose
    FROM tblStock AS S;
    

    请注意,我已重命名您的字段,因为 Date 是 Access 中的保留字。

    问候,

    【讨论】:

    • 这很可能是我的设计中的一个错误,但是我将日期存储为字符串,并且排序方法是将日期存储为相应日期的时间戳。我怎样才能让这个查询在这些条件下工作? - 原因是通过 ODBC 检索数据需要我将 Access 中的日期格式转换为 C++ 中的整数结构,然后将其转换为我的程序的字符串。这既慢又低效,所以我只存储了自 1970 年以来的秒数。这让我可以检索字符串日期以及要排序的秒数日期,这要快得多。
    • 查看CDateLeft/Mid/Right/DateSerial 的组合,将“日期”作为正确的DateType。
    • 我尝试了 DateValue(),考虑到它需要一个字符串,但是每个查询都需要一分钟以上,我将每个 S1.StockDate 包装在一个 DateValue 中,并且查询没有移动状态栏一个像素呢。与 CDate 的处理相同。
    • 这是所有从一开始就真正有用的信息。请修改您的问题以包含此信息,包括原始数据。
    • 我实际上添加了一个DateDate 字段,日期存储为实际日期。但是,查询运行速度极慢。此外,当它完成时,由于某种原因,过去 12 行的 MonthEnding 是相同的。
    猜你喜欢
    • 2022-08-20
    • 1970-01-01
    • 2018-03-16
    • 2017-07-23
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多