UPDATE qry Specifying Multiple Fields in Nested SELECT subqry | Newbie | | Join Date: Aug 2007
Posts: 9
| |
Hello all!
I don't know if this can even be done, but I'm sure you will either help or suggest another avenue to accomplish the same.
My problem may be a simple find duplicates / do something with only one of the duplicates issue, but I got to the point where an update query with a nested select subquery would work wonderfully, if only it would work!
I have several fields in a master Access 2000 table, some of which are id, fname, lname, and birth_date. I can't send two birthday cards to the same kid, so I dedup in my list based on fname, lname and birth_date. The id field is autonumber, so every id is unique. With the duplicates found, I'd like to null these three fields in only ONE of the entries. So I first wrote a select query that returned the result set I wanted to modify: -
SELECT DISTINCT [fname], MAX([id])
-
FROM master AS Tmp
-
GROUP BY [fname], [lname], [birth_date]
-
HAVING Count(*)>1 And [fname] = master.[fname] And [lname] = master.[lname] And [birth_date] = master.[birth_date];
-
This displays just one of each duplicate entry, so I then place it as a nested SELECT in an UPDATE query like so: -
UPDATE master SET [fname] = Null, [lname] = Null, [birth_date] = Null
-
WHERE (SELECT DISTINCT [fname], MAX([id])
-
FROM master AS Tmp
-
GROUP BY [fname], [lname], [birth_date]
-
HAVING Count(*)>1 And [fname] = master.[fname] And [lname] = master.[lname] And [birth_date] = master.[birth_date]);
-
This of course, results in access telling me I can't run this query:
"You have written a subquery that can return more than one field without using the EXISTS reserved word in the main query's FROM clause. Revise the SELECT statement of the subquery to request only one field."
Of course, modifying my SELECT query to filter by only one field would result in me seeing all entries that have duplicates. I've tried an AND to join two different SELECT subqueries but that of course doesn't work. I'm at wits end, but we do this manually now so it wouldn't be a big loss if what I want to do is out of the question.
I am new to the world of database management, and any kind of code writing, so I apologize if this is exceedingly basic. I appreciate any and all help!
-Eddie
|  | Expert | | Join Date: Apr 2006 Location: Philadelphia
Posts: 5,214
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by P3Eddie Hello all!
I don't know if this can even be done, but I'm sure you will either help or suggest another avenue to accomplish the same.
My problem may be a simple find duplicates / do something with only one of the duplicates issue, but I got to the point where an update query with a nested select subquery would work wonderfully, if only it would work!
I have several fields in a master Access 2000 table, some of which are id, fname, lname, and birth_date. I can't send two birthday cards to the same kid, so I dedup in my list based on fname, lname and birth_date. The id field is autonumber, so every id is unique. With the duplicates found, I'd like to null these three fields in only ONE of the entries. So I first wrote a select query that returned the result set I wanted to modify: -
SELECT DISTINCT [fname], MAX([id])
-
FROM master AS Tmp
-
GROUP BY [fname], [lname], [birth_date]
-
HAVING Count(*)>1 And [fname] = master.[fname] And [lname] = master.[lname] And [birth_date] = master.[birth_date];
-
This displays just one of each duplicate entry, so I then place it as a nested SELECT in an UPDATE query like so: -
UPDATE master SET [fname] = Null, [lname] = Null, [birth_date] = Null
-
WHERE (SELECT DISTINCT [fname], MAX([id])
-
FROM master AS Tmp
-
GROUP BY [fname], [lname], [birth_date]
-
HAVING Count(*)>1 And [fname] = master.[fname] And [lname] = master.[lname] And [birth_date] = master.[birth_date]);
-
This of course, results in access telling me I can't run this query:
"You have written a subquery that can return more than one field without using the EXISTS reserved word in the main query's FROM clause. Revise the SELECT statement of the subquery to request only one field."
Of course, modifying my SELECT query to filter by only one field would result in me seeing all entries that have duplicates. I've tried an AND to join two different SELECT subqueries but that of course doesn't work. I'm at wits end, but we do this manually now so it wouldn't be a big loss if what I want to do is out of the question.
I am new to the world of database management, and any kind of code writing, so I apologize if this is exceedingly basic. I appreciate any and all help!
-Eddie Here is one solution to your problem, it has been thoroughly tested and is fully functional:- Create qryUniqueDupIDs which does nothing more than display the MAXIMUM Unique ID Numbers for Duplicate Records. I used tblBirthdayCards for testing purposes, make your own substitutions.
-
SELECT DISTINCT Max(ID) AS Max_ID
-
FROM tblBirthdayCards
-
GROUP BY fname, lname, birth_date
-
HAVING fname=[fname] AND lname=[lname] AND birth_date=[birth_date] AND Count(*)>1;
-
- Create a Recordset based on this Query, and set the relevant, duplicate Fields to Null.
-
Dim MyDB As DAO.Database, MyRS As DAO.Recordset, MySQL As String
-
-
Set MyDB = CurrentDb()
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
-
MyRS.MoveFirst
-
-
DoCmd.SetWarnings False
-
Do While Not MyRS.EOF
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]=" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
Loop
-
DoCmd.SetWarnings True
-
-
MyRS.Close
-
- There is probably an easier, SQL approach, but since I am not that proficient in SQL, and I don't even like it, I provide you with this alternative.
- Let me know how you make out.
| | Newbie | | Join Date: Aug 2007
Posts: 9
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry
Wow, the thought of doing this in VB never crossed my mind, as a priority of mine of late has been to keep my form code as lean as possible. This worked wonderfully! Now I'll just find a way to automate the function to loop as many times as necessary (in the event of one entry having multiple duplicates, as this works for an entry having one duplicate. ) I expect an if statement in VB ought to do the trick, pointing at an EXISTS select query.
Thank you very much for your help, exactly what I needed!
|  | Expert | | Join Date: Apr 2006 Location: Philadelphia
Posts: 5,214
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by P3Eddie Wow, the thought of doing this in VB never crossed my mind, as a priority of mine of late has been to keep my form code as lean as possible. This worked wonderfully! Now I'll just find a way to automate the function to loop as many times as necessary (in the event of one entry having multiple duplicates, as this works for an entry having one duplicate. ) I expect an if statement in VB ought to do the trick, pointing at an EXISTS select query.
Thank you very much for your help, exactly what I needed! Glad I could help you. Just off the top of my head, you can check for the cases where there may be > 1 Duplicate via the DCount Function. If there are multiple Duplicates, then adjust the SQL Clause as indicated in Line #11. BTW, this would not involved any Looping Structure. - Dim MyDB As DAO.Database, MyRS As DAO.Recordset, MySQL As String
-
-
Set MyDB = CurrentDb()
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
-
MyRS.MoveFirst
-
-
DoCmd.SetWarnings False
-
Do While Not MyRS.EOF
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]<>" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
Loop
-
DoCmd.SetWarnings True
-
-
MyRS.Close
| | Newbie | | Join Date: Aug 2007
Posts: 9
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by ADezii Glad I could help you. Just off the top of my head, you can check for the cases where there may be > 1 Duplicate via the DCount Function. If there are multiple Duplicates, then adjust the SQL Clause as indicated in Line #11. BTW, this would not involved any Looping Structure. - Dim MyDB As DAO.Database, MyRS As DAO.Recordset, MySQL As String
-
-
Set MyDB = CurrentDb()
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
-
MyRS.MoveFirst
-
-
DoCmd.SetWarnings False
-
Do While Not MyRS.EOF
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]<>" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
Loop
-
DoCmd.SetWarnings True
-
-
MyRS.Close
Just thought you'd like to see what I came up with to resolve this thread. Any suggestions are appreciated (if you have any)! -
Private Sub Function4_Click()
-
-
On Error GoTo Err_Function4_Click
-
-
Dim MyDB As DAO.Database, MyRS As DAO.Recordset, MySQL As String, DTotal As Long
-
Set MyDB = currentdb()
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
MyRS.MoveFirst
-
-
GoTo NullDups
-
-
NullDups:
-
DoCmd.SetWarnings False
-
Do While Not MyRS.EOF
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]=" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
If MyRS.RecordCount = 0 Then Exit Do
-
Loop
-
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
DTotal = DCount("fname", "qryfinddups")
-
-
If DTotal = 0 Then MsgBox "Success" Else GoTo NullDups
-
-
DoCmd.SetWarnings True
-
-
MyRS.Close
-
-
Exit_Function4_Click:
-
Exit Sub
-
-
Err_Function4_Click:
-
MsgBox Err.Description
-
Resume Exit_Function4_Click
-
-
End Sub
-
|  | Expert | | Join Date: Apr 2006 Location: Philadelphia
Posts: 5,214
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by P3Eddie Just thought you'd like to see what I came up with to resolve this thread. Any suggestions are appreciated (if you have any)! -
Private Sub Function4_Click()
-
-
On Error GoTo Err_Function4_Click
-
-
Dim MyDB As DAO.Database, MyRS As DAO.Recordset, MySQL As String, DTotal As Long
-
Set MyDB = currentdb()
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
MyRS.MoveFirst
-
-
GoTo NullDups
-
-
NullDups:
-
DoCmd.SetWarnings False
-
Do While Not MyRS.EOF
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]=" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
If MyRS.RecordCount = 0 Then Exit Do
-
Loop
-
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
DTotal = DCount("fname", "qryfinddups")
-
-
If DTotal = 0 Then MsgBox "Success" Else GoTo NullDups
-
-
DoCmd.SetWarnings True
-
-
MyRS.Close
-
-
Exit_Function4_Click:
-
Exit Sub
-
-
Err_Function4_Click:
-
MsgBox Err.Description
-
Resume Exit_Function4_Click
-
-
End Sub
-
Just a couple of Items:- MyRS was already opened in Line #7, why are you re-opening the Recordset again in Line #22?
- Why Line #19? The Do..Loop structure will not allow the Recordset to reach EOF, and if there are no Records, the Loop will never be entered.
- Except in Error Traps, GoTo Statements are frowned upon, and should only be used in rare cases. They should be replaced with some kind of looping structure. I am referring to Lines 10 and 25.
- Nice job of following up!
| | Newbie | | Join Date: Aug 2007
Posts: 9
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by ADezii Just a couple of Items: - MyRS was already opened in Line #7, why are you re-opening the Recordset again in Line #22?
- Why Line #19? The Do..Loop structure will not allow the Recordset to reach EOF, and if there are no Records, the Loop will never be entered.
- Except in Error Traps, GoTo Statements are frowned upon, and should only be used in rare cases. They should be replaced with some kind of looping structure. I am referring to Lines 10 and 25.
- Nice job of following up!
1. I wasn't sure how to "refresh" the recordset to find the new set of duplicates. So say one entry had 2 duplicates, and two entries had one duplicate each, running the procedure exactly as you had it would result in the entry with two duplicates having only one duplicate. If I looped the procedure, it would be looking at the same recordset query, for which it had already updated the relevant fields. This accomplishes the equivalent of re-running the query to pull up the set of duplicates missed, if any.
2. Without this line, the procedure entered an endless loop. Not being familiar with looping structures, this was my failsafe to make sure it would come back out if it ended up updating a recordset with no records.
3. GoTo was more my way of segmenting everything. I originally had a Do...Loop within a Do...Loop that looked something like -
Do
-
Do While Not MyRS.EOF
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]=" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
Loop
-
Loop Until MyRS.RecordCount=0
-
This produced unpredictable results and more often than not resulted in an endless loop for my trouble. I know GoTo and hence why, but I'll take another stab at a loop structure. Part of my problem was determining that I was trying to loop back to update a recordset that had already been updating without telling access to pull up a new set of records to update every time it finished updating the last set until it returned no duplicates. To be honest, I didn't know it was frowned upon.
Thank you so much for your time and helpful comments! I will try it again and post it here if I can get one to work a little more neatly.
|  | Expert | | Join Date: Apr 2006 Location: Philadelphia
Posts: 5,214
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by P3Eddie 1. I wasn't sure how to "refresh" the recordset to find the new set of duplicates. So say one entry had 2 duplicates, and two entries had one duplicate each, running the procedure exactly as you had it would result in the entry with two duplicates having only one duplicate. If I looped the procedure, it would be looking at the same recordset query, for which it had already updated the relevant fields. This accomplishes the equivalent of re-running the query to pull up the set of duplicates missed, if any.
2. Without this line, the procedure entered an endless loop. Not being familiar with looping structures, this was my failsafe to make sure it would come back out if it ended up updating a recordset with no records.
3. GoTo was more my way of segmenting everything. I originally had a Do...Loop within a Do...Loop that looked something like -
Do
-
Do While Not MyRS.EOF
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]=" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
Loop
-
Loop Until MyRS.RecordCount=0
-
This produced unpredictable results and more often than not resulted in an endless loop for my trouble. I know GoTo and hence why, but I'll take another stab at a loop structure. Part of my problem was determining that I was trying to loop back to update a recordset that had already been updating without telling access to pull up a new set of records to update every time it finished updating the last set until it returned no duplicates. To be honest, I didn't know it was frowned upon.
Thank you so much for your time and helpful comments! I will try it again and post it here if I can get one to work a little more neatly. First of all, I commend your efforts. Please understand that I am not criticizing your work, but only making suggestions that will hopefully improve your overall understanding of the coding process, as well as making your code more efficient. All of us wish that a lot of the Members here would have your initiative. Keep up the good work! Quote:
I wasn't sure how to "refresh" the recordset to find the new set of duplicates.
- You can try the Requery Method of the Recordset Object. This Method will re-execute the Query on which the Object is based. Try replacing Line #22 with:
Quote:
this was my failsafe to make sure it would come back out if it ended up updating a recordset with no records
- If you wish to explicitly test a Recordset to make sure that it contains Records, it should be done immediately after its creation, before entering any code segments. The simplest means to do this is:
- Dim MyDB As DAO.Database, MyRS As DAO.Recordset, MySQL As String, DTotal As Long
-
Set MyDB = currentdb()
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
If MyRS.RecordCount > 0 Then
-
'you'll only get here if the Recordset contains Rows
-
Else
-
'get outta Dodge!
-
End If
| | Newbie | | Join Date: Aug 2007
Posts: 9
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by ADezii First of all, I commend your efforts. Please understand that I am not criticizing your work, but only making suggestions that will hopefully improve your overall understanding of the coding process, as well as making your code more efficient. All of us wish that a lot of the Members here would have your initiative. Keep up the good work! - You can try the Requery Method of the Recordset Object. This Method will re-execute the Query on which the Object is based. Try replacing Line #22 with:
- If you wish to explicitly test a Recordset to make sure that it contains Records, it should be done immediately after its creation, before entering any code segments. The simplest means to do this is:
- Dim MyDB As DAO.Database, MyRS As DAO.Recordset, MySQL As String, DTotal As Long
-
Set MyDB = currentdb()
-
Set MyRS = MyDB.OpenRecordset("qryUniqueDupIDs", dbOpenDynaset)
-
If MyRS.RecordCount > 0 Then
-
'you'll only get here if the Recordset contains Rows
-
Else
-
'get outta Dodge!
-
End If
No, please, I have no pride in this regard and I can only hope to make life a little easier for you guys that do know so I can learn and help others! I can't say enough how much I appreciate what you and the rest of the community here do for us "green" members!
So, I had already gotten a pretty lean block of code, and last post helped put the finishing touches. Now my entire sub consists (basically) of: -
Do While Not MyRS.RecordCount = 0
-
'This ought to exit the Do...Loop once #7 results in an empty RS (No Duplicates)
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]=" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
If MyRS.EOF Then MyRS.Requery
-
'Once the last duplicate in the RS has been updated, it ought to pull up an updated RS and
-
Loop
-
'Back to the criteria in #1
-
I've tested this and it seems to work without a hitch. If you could give this one last check I'd appreciate it tremendously!
-Eddie
|  | Expert | | Join Date: Apr 2006 Location: Philadelphia
Posts: 5,214
| | | re: UPDATE qry Specifying Multiple Fields in Nested SELECT subqry Quote:
Originally Posted by P3Eddie No, please, I have no pride in this regard and I can only hope to make life a little easier for you guys that do know so I can learn and help others! I can't say enough how much I appreciate what you and the rest of the community here do for us "green" members!
So, I had already gotten a pretty lean block of code, and last post helped put the finishing touches. Now my entire sub consists (basically) of: -
Do While Not MyRS.RecordCount = 0
-
'This ought to exit the Do...Loop once #7 results in an empty RS (No Duplicates)
-
MySQL = "Update tblBirthdayCards Set [fname] = Null, [lname] = Null, "
-
MySQL = MySQL & "[birth_date] = Null Where [ID]=" & MyRS![Max_ID]
-
DoCmd.RunSQL MySQL
-
MyRS.MoveNext
-
If MyRS.EOF Then MyRS.Requery
-
'Once the last duplicate in the RS has been updated, it ought to pull up an updated RS and
-
Loop
-
'Back to the criteria in #1
-
I've tested this and it seems to work without a hitch. If you could give this one last check I'd appreciate it tremendously!
-Eddie It's a slightly different approach, but if it works without a hitch, and you are happy with it, I'd say that ypu got a winner! Congratulations! One aspect of the beauty of programming is that there are usually many different ways to accomplish the same thing. See you around TheScripts.
|  | Similar Microsoft Access / VBA bytes | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,439 network members.
|