MS-Access VBA SQL, If condition in subquery, 效率提升
MS-Access VBA SQL, If condition in subquery, efficiency and improvement
我已经设法让我的代码工作,但是执行需要很长时间。在执行最终 SQL 语句并将该行写入 table.
之前,我使用一系列打开和关闭记录集语句来获取我正在寻找的 addr_ImportID
是否有更好的方法来使用更好的子查询、case 语句、if 条件或其他方式来完成我想要实现的目标?我对子查询的使用正在减慢速度,因此在不打开和关闭记录集的情况下操作数据可能会更有效率。或者更好的一系列 select 语句?
这是 table 的示例:
CnBio_ID | Addr_Type | Addr_ImportID | CnAdrAll_1_IDKEY | CnAdrAll_1_DateLastChanged
0001009 | Previous | 12344 | 1 | 03/15/2014
0001009 | Home | H2345 | 3 | 01/02/2017
0001009 | Home | A2344 | 2 | 01/02/2017
1223144 | Previous | 23441 | 7 | 05/23/2010
1223144 | Other | 31333 | 6 | 08/21/2016
1223144 | Previous | 45848 | 5 | 08/21/2016
下面的代码片段是我的代码的一部分。
strSql2 = "SELECT Addr_ImportID From [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' " & _
"AND CnAdrAll_1_DateLastChanged IN (SELECT Max(CnAdrAll_1_DateLastChanged) FROM [Non-Preferred Home Addresses] " & _
"Where CnBio_ID = '" & rs(0) & "' AND Addr_ImportID IN (SELECT Addr_ImportID From [Non-Preferred Home Addresses] " & _
"WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home'));"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
If Not (rsMaxAddressImportID.EOF) Then
'Condition where more than one Home address exists updated on the same date
If (rsMaxAddressImportID.RecordCount > 1) Then
rsMaxAddressImportID.Close
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] WHERE CnAdrAll_1_IDKEY = " & _
"(SELECT Max(CnAdrAll_1_IDKEY) FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home');"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
MsgBox "Row = " & i
End If
- 每个 CnBio_ID
- 如果家庭地址存在,select Addr_ImportID 具有最大 DateLastChanged 的行
- 如果多个家庭地址在同一日期最后更新,select Addr_ImportID 行最大 CnAdrAll_1_IDKEY
- 如果没有家庭住址,select Addr_ImportID 具有最大 DateLastChanged 的行
- 如果多个地址在同一日期最后更新,select Addr_ImportID 行最大 CnAdrAll_1_IDKEY
在 Parfait 提问后更新
'Select Distinct CIDs to loop through
'strSql = "SELECT CnBio_ID FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & ConstID & "'Group By CnBio_ID;"
strSql = "SELECT CnBio_ID FROM [Non-Preferred Home Addresses] Group By CnBio_ID;"
Set rs = DBEngine(0)(0).OpenRecordset(strSql, dbOpenDynaset)
If Not (rs.EOF And rs.BOF) Then
'MsgBox rs.RecordCount
'This section will loop through all distinct CIDs.
i = 1
Do Until rs.EOF
'Select Non-Preferred Home Address with latest date updated
strSql2 = "SELECT Addr_ImportID From [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' " & _
"AND CnAdrAll_1_DateLastChanged IN (SELECT Max(CnAdrAll_1_DateLastChanged) FROM [Non-Preferred Home Addresses] " & _
"Where CnBio_ID = '" & rs(0) & "' AND Addr_ImportID IN (SELECT Addr_ImportID From [Non-Preferred Home Addresses] " & _
"WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home'));"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
If Not (rsMaxAddressImportID.EOF) Then
'Condition where more than one Home address exists updated on the same date
If (rsMaxAddressImportID.RecordCount > 1) Then
rsMaxAddressImportID.Close
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] WHERE CnAdrAll_1_IDKEY = " & _
"(SELECT Max(CnAdrAll_1_IDKEY) FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home');"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
MsgBox "Row = " & i
End If
'rsMaxAddressImportID.Close
Else
'Condition if all non-preferred addresses are not Home
rsMaxAddressImportID.Close
'Select max date last updated for next select statement
maxDateSql = "SELECT Max(CnAdrAll_1_DateLastChanged) " & _
"FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "';"
Set rs2 = DBEngine(0)(0).OpenRecordset(maxDateSql, dbOpenDynaset)
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] " & _
"WHERE [Non-Preferred Home Addresses].CnBio_ID = '" & rs(0) & "' " & _
"AND [Non-Preferred Home Addresses].CnAdrAll_1_DateLastChanged = #" & rs2(0) & "#;"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
'MsgBox rsMaxAddressImportID(0)
If Not (rsMaxAddressImportID.EOF) Then
'MsgBox rsMaxAddressImportID.RecordCount
If (rsMaxAddressImportID.RecordCount > 1) Then
rsMaxAddressImportID.Close
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] WHERE CnAdrAll_1_IDKEY = " & _
"(SELECT Max(CnAdrAll_1_IDKEY) FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' AND CnAdrAll_1_DateLastChanged = #" & rs2(0) & "#);"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
'MsgBox rsMaxAddressImportID(0)
End If
End If
End If
'Get Actual address line
'DoCmd.RunSQL "SELECT * INTO " & _
"[Tbl_Max_Non-Preferred_Address] " & _
"FROM [Non-Preferred Home Addresses] WHERE [Non-Preferred Home Addresses].Addr_ImportID = '" & rsMaxAddressImportID(0) & "';"
DoCmd.RunSQL "INSERT INTO [Tbl_Max_Non-Preferred_Address] SELECT * FROM [Non-Preferred Home Addresses] WHERE [Non-Preferred Home Addresses].Addr_ImportID = '" & rsMaxAddressImportID(0) & "';"
rsMaxAddressImportID.Close
rs.MoveNext
i = i + 1
Loop
Else
MsgBox "There are no records in the recordset."
End If
rs.Close
- "Home" 地址的意义在于,一些选民没有 "Home" 地址(参见 CnBio_ID 1223144)。
- rs 是要循环的唯一 CnBio_IDs 的选择。
Thomas G 解决后更新:
总的来说,一切似乎都取得了不错的结果,但我认为存在 sorting/order 问题,我似乎无法获得正确的语法来测试。我不断收到语法错误。我对括号等的访问解释不够熟悉,无法正确处理。我正在尝试 运行 以下内容:
strSql_1 = "INSERT INTO [Table1] SELECT 1 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.Addr_IDKEY) AS MAX_IDKey " & _
"FROM [TB - Non-Preferred Addresses] T1 " & _
"INNER JOIN " & _
"(" & _
"SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date " & _
"FROM [TB - Non-Preferred Addresses] " & _
"WHERE (Addr_Type = 'Home' AND CnBio_ID = '0106228') " & _
"GROUP BY CnBio_ID " & _
") T2 ON T1.CnBio_ID = T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged = T2.Max_Date " & _
"WHERE Addr_Type = 'Home' " & _
"GROUP BY T1.CnBio_ID, T2.Max_Date "
strSql_2 = " UNION ALL SELECT 2 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.Addr_IDKEY) AS MAX_IDKey " & _
"FROM [TB - Non-Preferred Addresses] T1 " & _
"INNER JOIN " & _
"(" & _
"SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date " & _
"FROM [TB - Non-Preferred Addresses] " & _
"WHERE (Addr_Type IN ('Campus','Harris Home', 'NCOA2003','Other','Previous','Previous Home','Previous Student','Seasonal','Student') AND CnBio_ID = '0106228') " & _
"GROUP BY CnBio_ID " & _
") T2 ON T1.CnBio_ID = T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged = T2.Max_Date " & _
"WHERE (Addr_Type IN ('Campus','Harris Home', 'NCOA2003','Other','Previous','Previous Home','Previous Student','Seasonal','Student') AND T1.CnBio_ID = '0106228') " & _
"GROUP BY T1.CnBio_ID, T2.Max_Date " & _
"ORDER BY CnBio_ID, priority"
这应该可以解决问题 SQL
SELECT V.CnBio_ID, FIRST(T.Addr_ImportID) AS Addr_ImportID , FIRST(V.Max_Date) AS CnAdrAll_1_DateLastChanged, FIRST(V.MAX_IDKey) AS CnAdrAll_1_IDKEY
FROM [Non-Preferred Home Addresses] T
INNER JOIN
(
SELECT 1 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.CnAdrAll_1_IDKEY) AS MAX_IDKey
FROM [Non-Preferred Home Addresses] T1
INNER JOIN
(
SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date
FROM [Non-Preferred Home Addresses]
WHERE Addr_Type = 'Home'
GROUP BY CnBio_ID
) T2 ON T1.CnBio_ID=T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged=T2.Max_Date
WHERE Addr_Type = 'Home'
GROUP BY T1.CnBio_ID, T2.Max_Date
UNION ALL
SELECT 2 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.CnAdrAll_1_IDKEY) AS MAX_IDKey
FROM [Non-Preferred Home Addresses] T1
INNER JOIN
(
SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date
FROM [Non-Preferred Home Addresses]
WHERE Addr_Type <> 'Home'
GROUP BY CnBio_ID
) T2 ON T1.CnBio_ID=T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged=T2.Max_Date
WHERE Addr_Type <> 'Home'
GROUP BY T1.CnBio_ID, T2.Max_Date
ORDER BY CnBio_ID, priority
) V
ON T.CnBio_ID = V.CnBio_ID AND T.CnAdrAll_1_DateLastChanged=V.Max_Date AND T.CnAdrAll_1_IDKEY = V.MAX_IDKey
GROUP BY V.CnBio_ID
对于您的 table 中的每个 CnBio_ID,它将保留与您的日期逻辑相匹配的记录。您可以从中创建一个视图(查询),然后使用 CnBio_ID=anything 查询它以检索任何 CnBio_ID
的信息
不过我不知道性能是否可以接受table,主要取决于你table.
中的记录数
你应该在 :
上有索引
- CnBio_ID
- Addr_Type
- CnAdrAll_1_IDKEY
- CnAdrAll_1_DateLastChanged
如果您的类型数量有限而不是 "Home",从性能的角度来看,明确命名它们而不是搜索“<> 'HOME'
”要好得多,所以你必须改变这个:
WHERE Addr_Type <> 'Home'
到这个
WHERE Addr_Type IN ('Previous','Other')
(2 次)
如果您真的不明白发生了什么,或者需要一些解释,请告诉我。
我不想无缘无故地进行冗长的解释。
从分解和 运行 所有子查询开始,您应该会更好地理解它。
更新
要在您的代码中使用我的查询,请不要在 VBA 中硬核它!使用查询设计器从中创建查询(在标准 SQL 中,这称为视图)。
Query Designer Example in MS Access 2016
当您在设计器中时,切换到 SQL 视图。 COpy/Paste 我的查询并保存。将其命名为 Instance QRY_foo
它现在将充当 table
然后在您的 VBA 中执行此操作:
strSql2 = "SELECT * FROM QRY_Foo"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
这样您就可以更轻松地调整查询,只需从查询设计器中进行即可。
我已经设法让我的代码工作,但是执行需要很长时间。在执行最终 SQL 语句并将该行写入 table.
之前,我使用一系列打开和关闭记录集语句来获取我正在寻找的 addr_ImportID是否有更好的方法来使用更好的子查询、case 语句、if 条件或其他方式来完成我想要实现的目标?我对子查询的使用正在减慢速度,因此在不打开和关闭记录集的情况下操作数据可能会更有效率。或者更好的一系列 select 语句?
这是 table 的示例:
CnBio_ID | Addr_Type | Addr_ImportID | CnAdrAll_1_IDKEY | CnAdrAll_1_DateLastChanged
0001009 | Previous | 12344 | 1 | 03/15/2014
0001009 | Home | H2345 | 3 | 01/02/2017
0001009 | Home | A2344 | 2 | 01/02/2017
1223144 | Previous | 23441 | 7 | 05/23/2010
1223144 | Other | 31333 | 6 | 08/21/2016
1223144 | Previous | 45848 | 5 | 08/21/2016
下面的代码片段是我的代码的一部分。
strSql2 = "SELECT Addr_ImportID From [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' " & _
"AND CnAdrAll_1_DateLastChanged IN (SELECT Max(CnAdrAll_1_DateLastChanged) FROM [Non-Preferred Home Addresses] " & _
"Where CnBio_ID = '" & rs(0) & "' AND Addr_ImportID IN (SELECT Addr_ImportID From [Non-Preferred Home Addresses] " & _
"WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home'));"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
If Not (rsMaxAddressImportID.EOF) Then
'Condition where more than one Home address exists updated on the same date
If (rsMaxAddressImportID.RecordCount > 1) Then
rsMaxAddressImportID.Close
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] WHERE CnAdrAll_1_IDKEY = " & _
"(SELECT Max(CnAdrAll_1_IDKEY) FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home');"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
MsgBox "Row = " & i
End If
- 每个 CnBio_ID
- 如果家庭地址存在,select Addr_ImportID 具有最大 DateLastChanged 的行
- 如果多个家庭地址在同一日期最后更新,select Addr_ImportID 行最大 CnAdrAll_1_IDKEY
- 如果没有家庭住址,select Addr_ImportID 具有最大 DateLastChanged 的行
- 如果多个地址在同一日期最后更新,select Addr_ImportID 行最大 CnAdrAll_1_IDKEY
在 Parfait 提问后更新
'Select Distinct CIDs to loop through
'strSql = "SELECT CnBio_ID FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & ConstID & "'Group By CnBio_ID;"
strSql = "SELECT CnBio_ID FROM [Non-Preferred Home Addresses] Group By CnBio_ID;"
Set rs = DBEngine(0)(0).OpenRecordset(strSql, dbOpenDynaset)
If Not (rs.EOF And rs.BOF) Then
'MsgBox rs.RecordCount
'This section will loop through all distinct CIDs.
i = 1
Do Until rs.EOF
'Select Non-Preferred Home Address with latest date updated
strSql2 = "SELECT Addr_ImportID From [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' " & _
"AND CnAdrAll_1_DateLastChanged IN (SELECT Max(CnAdrAll_1_DateLastChanged) FROM [Non-Preferred Home Addresses] " & _
"Where CnBio_ID = '" & rs(0) & "' AND Addr_ImportID IN (SELECT Addr_ImportID From [Non-Preferred Home Addresses] " & _
"WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home'));"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
If Not (rsMaxAddressImportID.EOF) Then
'Condition where more than one Home address exists updated on the same date
If (rsMaxAddressImportID.RecordCount > 1) Then
rsMaxAddressImportID.Close
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] WHERE CnAdrAll_1_IDKEY = " & _
"(SELECT Max(CnAdrAll_1_IDKEY) FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' AND Addr_Type = 'Home');"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
MsgBox "Row = " & i
End If
'rsMaxAddressImportID.Close
Else
'Condition if all non-preferred addresses are not Home
rsMaxAddressImportID.Close
'Select max date last updated for next select statement
maxDateSql = "SELECT Max(CnAdrAll_1_DateLastChanged) " & _
"FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "';"
Set rs2 = DBEngine(0)(0).OpenRecordset(maxDateSql, dbOpenDynaset)
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] " & _
"WHERE [Non-Preferred Home Addresses].CnBio_ID = '" & rs(0) & "' " & _
"AND [Non-Preferred Home Addresses].CnAdrAll_1_DateLastChanged = #" & rs2(0) & "#;"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
'MsgBox rsMaxAddressImportID(0)
If Not (rsMaxAddressImportID.EOF) Then
'MsgBox rsMaxAddressImportID.RecordCount
If (rsMaxAddressImportID.RecordCount > 1) Then
rsMaxAddressImportID.Close
strSql2 = "SELECT Addr_ImportID FROM [Non-Preferred Home Addresses] WHERE CnAdrAll_1_IDKEY = " & _
"(SELECT Max(CnAdrAll_1_IDKEY) FROM [Non-Preferred Home Addresses] WHERE CnBio_ID = '" & rs(0) & "' AND CnAdrAll_1_DateLastChanged = #" & rs2(0) & "#);"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
'MsgBox rsMaxAddressImportID(0)
End If
End If
End If
'Get Actual address line
'DoCmd.RunSQL "SELECT * INTO " & _
"[Tbl_Max_Non-Preferred_Address] " & _
"FROM [Non-Preferred Home Addresses] WHERE [Non-Preferred Home Addresses].Addr_ImportID = '" & rsMaxAddressImportID(0) & "';"
DoCmd.RunSQL "INSERT INTO [Tbl_Max_Non-Preferred_Address] SELECT * FROM [Non-Preferred Home Addresses] WHERE [Non-Preferred Home Addresses].Addr_ImportID = '" & rsMaxAddressImportID(0) & "';"
rsMaxAddressImportID.Close
rs.MoveNext
i = i + 1
Loop
Else
MsgBox "There are no records in the recordset."
End If
rs.Close
- "Home" 地址的意义在于,一些选民没有 "Home" 地址(参见 CnBio_ID 1223144)。
- rs 是要循环的唯一 CnBio_IDs 的选择。
Thomas G 解决后更新:
总的来说,一切似乎都取得了不错的结果,但我认为存在 sorting/order 问题,我似乎无法获得正确的语法来测试。我不断收到语法错误。我对括号等的访问解释不够熟悉,无法正确处理。我正在尝试 运行 以下内容:
strSql_1 = "INSERT INTO [Table1] SELECT 1 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.Addr_IDKEY) AS MAX_IDKey " & _
"FROM [TB - Non-Preferred Addresses] T1 " & _
"INNER JOIN " & _
"(" & _
"SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date " & _
"FROM [TB - Non-Preferred Addresses] " & _
"WHERE (Addr_Type = 'Home' AND CnBio_ID = '0106228') " & _
"GROUP BY CnBio_ID " & _
") T2 ON T1.CnBio_ID = T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged = T2.Max_Date " & _
"WHERE Addr_Type = 'Home' " & _
"GROUP BY T1.CnBio_ID, T2.Max_Date "
strSql_2 = " UNION ALL SELECT 2 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.Addr_IDKEY) AS MAX_IDKey " & _
"FROM [TB - Non-Preferred Addresses] T1 " & _
"INNER JOIN " & _
"(" & _
"SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date " & _
"FROM [TB - Non-Preferred Addresses] " & _
"WHERE (Addr_Type IN ('Campus','Harris Home', 'NCOA2003','Other','Previous','Previous Home','Previous Student','Seasonal','Student') AND CnBio_ID = '0106228') " & _
"GROUP BY CnBio_ID " & _
") T2 ON T1.CnBio_ID = T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged = T2.Max_Date " & _
"WHERE (Addr_Type IN ('Campus','Harris Home', 'NCOA2003','Other','Previous','Previous Home','Previous Student','Seasonal','Student') AND T1.CnBio_ID = '0106228') " & _
"GROUP BY T1.CnBio_ID, T2.Max_Date " & _
"ORDER BY CnBio_ID, priority"
这应该可以解决问题 SQL
SELECT V.CnBio_ID, FIRST(T.Addr_ImportID) AS Addr_ImportID , FIRST(V.Max_Date) AS CnAdrAll_1_DateLastChanged, FIRST(V.MAX_IDKey) AS CnAdrAll_1_IDKEY
FROM [Non-Preferred Home Addresses] T
INNER JOIN
(
SELECT 1 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.CnAdrAll_1_IDKEY) AS MAX_IDKey
FROM [Non-Preferred Home Addresses] T1
INNER JOIN
(
SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date
FROM [Non-Preferred Home Addresses]
WHERE Addr_Type = 'Home'
GROUP BY CnBio_ID
) T2 ON T1.CnBio_ID=T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged=T2.Max_Date
WHERE Addr_Type = 'Home'
GROUP BY T1.CnBio_ID, T2.Max_Date
UNION ALL
SELECT 2 AS priority, T1.CnBio_ID, T2.Max_Date, MAX(T1.CnAdrAll_1_IDKEY) AS MAX_IDKey
FROM [Non-Preferred Home Addresses] T1
INNER JOIN
(
SELECT CnBio_ID , MAX(CnAdrAll_1_DateLastChanged) AS Max_Date
FROM [Non-Preferred Home Addresses]
WHERE Addr_Type <> 'Home'
GROUP BY CnBio_ID
) T2 ON T1.CnBio_ID=T2.CnBio_ID AND T1.CnAdrAll_1_DateLastChanged=T2.Max_Date
WHERE Addr_Type <> 'Home'
GROUP BY T1.CnBio_ID, T2.Max_Date
ORDER BY CnBio_ID, priority
) V
ON T.CnBio_ID = V.CnBio_ID AND T.CnAdrAll_1_DateLastChanged=V.Max_Date AND T.CnAdrAll_1_IDKEY = V.MAX_IDKey
GROUP BY V.CnBio_ID
对于您的 table 中的每个 CnBio_ID,它将保留与您的日期逻辑相匹配的记录。您可以从中创建一个视图(查询),然后使用 CnBio_ID=anything 查询它以检索任何 CnBio_ID
的信息不过我不知道性能是否可以接受table,主要取决于你table.
中的记录数你应该在 :
上有索引- CnBio_ID
- Addr_Type
- CnAdrAll_1_IDKEY
- CnAdrAll_1_DateLastChanged
如果您的类型数量有限而不是 "Home",从性能的角度来看,明确命名它们而不是搜索“<> 'HOME'
”要好得多,所以你必须改变这个:
WHERE Addr_Type <> 'Home'
到这个
WHERE Addr_Type IN ('Previous','Other')
(2 次)
如果您真的不明白发生了什么,或者需要一些解释,请告诉我。 我不想无缘无故地进行冗长的解释。 从分解和 运行 所有子查询开始,您应该会更好地理解它。
更新
要在您的代码中使用我的查询,请不要在 VBA 中硬核它!使用查询设计器从中创建查询(在标准 SQL 中,这称为视图)。 Query Designer Example in MS Access 2016
当您在设计器中时,切换到 SQL 视图。 COpy/Paste 我的查询并保存。将其命名为 Instance QRY_foo
它现在将充当 table
然后在您的 VBA 中执行此操作:
strSql2 = "SELECT * FROM QRY_Foo"
Set rsMaxAddressImportID = DBEngine(0)(0).OpenRecordset(strSql2, dbOpenDynaset)
这样您就可以更轻松地调整查询,只需从查询设计器中进行即可。