目标:我有一堆日期,我想按类别更新最短日期的记录:
JVID APDATE TAG into > JVID APDATE TAG
1 201501 Use 1 201501 Don't Use
1 201502 Use 1 201502 Use
1 201502 Use 1 201502 Use
1 201503 Use 1 201503 Use
2 201502 Use 2 201502 Don't Use
2 201503 Use 2 201503 Use
我使用的方法如下: 我创建了一个字典,其中Key = ID,Value = MinDateByID 然后我循环遍历键(对于字典中的每个键),并为检查IIF语句更新的每个ID运行更新查询。使用/不要根据与最小日期匹配的日期使用。
这样做有效,但w / + 80k ID覆盖了+ 1M记录,它需要永远。
我考虑运行相同的东西,但是倾销SQL并且只是遍历记录,但我无法想象会更快?
我正在寻找SQL或VBA建议。
提前谢谢!
编辑 - 从评论添加SQL
UPDATE [FY16 Q12 BE] SET [FY16 Q12 BE].[Record Use] = IIF([FY16 Q12 BE].[Date] = "201601", "Use", "Don't Use") WHERE ([FY16 Q12 BE].[ID]="20165645699");
我浏览每个字典键/值对ex(20165645699,201601) 以80k +次的各种形式创建和运行此脚本
答案 0 :(得分:1)
MS Access在联接更新中比主流数据库更具限制性,因此我不得不使用临时表T2来保存最小值。
SELECT T1.ID, MIN(T1.RDate) AS MinDate INTO T2
FROM Test1
GROUP BY T1.ID;
现在我可以执行联接更新:
UPDATE T1 LEFT JOIN T2
ON T1.ID=T2.ID AND T1.RDate=T2.MinDate;
最后,我删除临时表:
DROP T2;
SET TAG = IIF(T2.ID IS NULL, "Don't Use", "Use");
[我已将您的表格T1命名为日期字段RDate,以避免与保留字词发生冲突。]
这可以通过在T2上添加主键(ID,MinDate)和在T1上添加索引(ID,RDate)来进一步加速。
答案 1 :(得分:0)
我认为您可以使用一个更新查询来执行此操作 - 或者至少在一个SQL语句中使用多个查询的组合。
我将使用您的示例数据,因为我无法弄清楚您的评论中您的实际表格或字段名称。
您需要将Table4替换为您的表名 - 以及ID /日期/标记字段以匹配您的列名。
更新SQL:
UPDATE Table4 SET Table4.Tag = "Don't Use"
WHERE ([Date] & "-" & [ID])
In (SELECT MergeID FROM
(SELECT Mins.[MinOfDate] & "-" & [ID] AS MergeID
FROM
(SELECT Table4.ID, Min(Table4.Date) AS MinOfDate
FROM Table4
WHERE Table4.Tag="Use"
GROUP BY Table4.ID) AS Mins) AS Merges);
如果您不需要标准来检查尚未更改的标签,那么您可以取消标准WHERE Table4.Tag="Use"
其他'无标签检查' OPTION 强>
更新SQL:
UPDATE Table4 SET Table4.Tag = "Don't Use"
WHERE ([Date] & "-" & [ID])
In (SELECT MergeID FROM
(SELECT Mins.[MinOfDate] & "-" & [ID] AS MergeID
FROM
(SELECT Table4.ID, Min(Table4.Date) AS MinOfDate
FROM Table4
GROUP BY Table4.ID) AS Mins) AS Merges);
答案 2 :(得分:0)
我想建议一下。但我发现你有重复的日期,我不确定你是否打算在最早的约会时有这些处理。
update [FY16 Q12 BE]
set TAG = "Don't use"
where not exists (
select 1 from [FY16 Q12 BE] as t2
where t2.ID = [FY16 Q12 BE].ID and t2.[DATE] < [FY16 Q12 BE].[DATE]
)
答案 3 :(得分:0)
我选择了迭代方法 - 我不确定为什么它比上面的SQL选项大纲要快得多,但它确实可以解决问题。感谢您的反馈。
Sub MinAPInclude(ByVal Tablename As String)
Dim db As DAO.Database
Dim qd As DAO.QueryDef
Dim rs As DAO.Recordset
Dim strList As String
Dim JVMinAP As Dictionary
Set JVMinAP = New Dictionary
Set db = DBEngine(0)(0)
Dim rst As DAO.Recordset
If Not DoesFieldExist(Tablename, "APDate") Then Exit Sub
SQLStatement = "SELECT [" & Tablename & "].[JVID], Min([" & Tablename & "].[APDate]) AS TargetAP"
SQLStatement = SQLStatement & " FROM [" & Tablename & "]"
SQLStatement = SQLStatement & " GROUP BY [" & Tablename & "].[JVID];"
Set qd = db.CreateQueryDef("", SQLStatement)
Set rs = qd.OpenRecordset
rs.MoveFirst
Do Until rs.EOF
If Not IsNull(rs("JVID")) Then
If Not JVMinAP.Exists(CStr(rs("JVID"))) Then
MinAP = rs("TargetAP")
JVMinAP.Add CStr(rs("JVID")), MinAP
End If
End If
rs.MoveNext
Loop
rs.Close
Set rst = db.OpenRecordset(Tablename)
rst.MoveFirst
Do Until rst.EOF
If rst("Record Use") <> "Include" Then
If rst("APDate") = JVMinAP(CStr(rst("JVID"))) Then
rst.Edit
rst("Record Use") = "Include"
rst.Update
End If
End If
rst.MoveNext
Loop
rst.Close
Set rst = nothing
Set rs = Nothing
Set qd = Nothing
Set db = Nothing
End Sub