【问题标题】:Assigning a missing rating to a date based on a rating on a different date根据不同日期的评级将缺失的评级分配给日期
【发布时间】:2020-04-10 08:20:35
【问题描述】:

我有一个在特定日期 (RatingDate) 应用的公司 (CoID) 评级 (Rating) 列表。

评级日期是零星的,我希望通过将给定评级分配给日期列表中的特定日期来填补空白。

如果评级在给定的 RatingDate 发生变化,新的评级将在更改后的日期结转。
我的代码会继承最旧的评分,并且如果评分在特定日期发生变化,则不会更改。

Public Function PopulateTableOfRatingHistory()
    
    Dim dbs As DAO.Database
    Set dbs = CurrentDb
    
    Dim dtDate As Date 'snapshot date
    Dim sqlAppend As String
    
    Dim sqlQueryLastRating As String
       
    Dim qdf As DAO.QueryDef
    Dim rs1 As DAO.Recordset
    Set rs1 = dbs.OpenRecordset("DATES") 'check this to make sure it imports the table values
    
    DoCmd.SetWarnings False
        
    rs1.MoveFirst
    Do While Not rs1.EOF
        'get the date value to use as a parameter
        dtDate = rs1.Fields(1).Value ' get the date value to lookup
        
        'use the date parameter to run the SQL for the last rating as of the given date and append the query result to a table
            
        DoCmd.RunSQL "INSERT INTO tblCoDtRtgs (ISIN, CoID, SnapDate, Rating, RatingDate ) SELECT RatingsBackDated.ISIN, RatingsBackDated.CoID, #" & dtDate & "#, Last(RatingsBackDated.Rating) AS LastOfRating, Last(RatingsBackDated.Date) AS LastOfDate " & _
          "FROM RatingsBackDated " & _
          "WHERE (((RatingsBackDated.Date)<= #" & dtDate & "#)) " & _
          "GROUP BY RatingsBackDated.name, RatingsBackDated.CoID, RatingsBackDated.ISIN;"
        
        rs1.MoveNext
    Loop
        
    rs1.Close
    Set rs1 = Nothing
    Set dbs = Nothing
      
    DoCmd.SetWarnings True
      
End Function

【问题讨论】:

  • 编辑问题以显示示例数据和所需结果 - 作为文本表格,而不是图像。
  • 聚合函数 First 和 Last 在没有定义排序顺序的情况下是不可靠的。评论support.office.com/en-us/article/…
  • 日期和名称是保留字,实际上不应该使用保留字作为任何东西的名称。

标签: vba loops ms-access


【解决方案1】:

考虑没有循环的纯 SQL,您首先使用交叉连接填充表,以获取 ISINCoIDSnapDateRatingRatingDate 的所有组合,然后使用嵌套域聚合:

  1. DMax 通过CoId 查找相对于SnapDate 的最新RatingDate
  2. DLookUp 通过CoId 检索步骤 1 日期的特定 Rating

两个查询都可以在外部(通过 Access GUI 查询设计 > ! Run)或 VBA 内部处理,如下所示。

SQL

追加查询(使用逗号分隔表的交叉连接)

INSERT INTO tblCoDtRtgs (ISIN, CoID, SnapDate, Rating, RatingDate ) 
SELECT r.ISIN, r.CoID, d.[Date], r.Rating, r.[Date]
FROM (SELECT ISIN, CoID,  Rating, [Date], FROM RatingsBackDated) r, 
      Dates d;

更新查询(域聚合可更新)

UPDATE tblCoDtRtgs r
SET r.Rating = DLookUp("Rating", "tblCoDtRtgs", 
                       "RatingDate = #" & NZ(DMax("RatingDate", "tblCoDtRtgs", 
                                               "[Date] < #" & r.Date & "#
                                                AND CoId = " & r.CoID),
                                             CDate('1900-01-01')) & "#
                        AND CoId = " & r.CoID);

VBA

' WITH WARNINGS (NO NEED TO CLOSE ACTION QUERIES)
DoCmd.OpenQuery myAppendQuery
DoCmd.OpenQuery myUpdateQuery


' WITHOUT WARNINGS
CurrentDb.Execute myAppendQuery
CurrentDb.Execute myUpdateQuery

【讨论】:

  • 非常感谢您回复我,直到明天我才有机会尝试这个,但我会告诉您进展如何!
  • 追加查询显示“选择语句包含保留字或参数名称拼写错误或丢失或标点不正确”,更新查询显示“查询中的语法错误(缺少运算符)表达”,有什么想法吗?再次感谢您。
  • 我编辑了语法问题,现在在 Access 中进行了测试,我颠倒了 DMax 的先前逻辑并翻转了不等号并添加了 NZ
【解决方案2】:

.. 如果评级在特定日期发生变化,则不会改变。

您可能需要正确格式化日期值的表达式 - 您可能希望使用 Max,而不是 Last

DoCmd.RunSQL "INSERT INTO tblCoDtRtgs (ISIN, CoID, SnapDate, Rating, RatingDate ) " & _
            "SELECT RatingsBackDated.ISIN, RatingsBackDated.CoID, #" & Format(dtDate, "yyyy\/mm\/dd") & "#, Max(RatingsBackDated.Rating) AS LastOfRating, Max(RatingsBackDated.Date) AS LastOfDate " & _
            "FROM RatingsBackDated " & _
            "WHERE (((RatingsBackDated.Date)<= #" & Format(dtDate, "yyyy\/mm\/dd") & "#)) " & _
            "GROUP BY RatingsBackDated.name, RatingsBackDated.CoID, RatingsBackDated.ISIN;"

【讨论】:

  • 谢谢 Gustav,不幸的是,这导致了相同的结果,它返回的是带有新日期的数据,但它也只返回最旧的评级,而不是在更改时更新它。跨度>
【解决方案3】:

通过更改解决了该问题: Last(RatingsBackDated.Rating) AS LastOfRating, Last(RatingsBackDated.Date) AS LastOfDate " & _

到: Min(RatingsBackDated.Rating) AS MinOfRating, Max(RatingsBackDated.Date) AS MaxOfDate " & _

感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 2020-02-21
    相关资源
    最近更新 更多