ok john, it sounds like you're looking for a hierarchy that's going to be driven by nested conditionals. if that doesn't make sense to you, consider this set of statements ("EO" = "either or":
Code:
if middle name (full) in EO then
find first/last matches WITH middle name included in output
elseif middle initial only in EO then
find first/last matches only WITH middle initial included in output
else
find first/last matches only in output
end if
obviously you have to use some code here, because the variables are too complex in the situation. if what I said above is correct John, the first thing i think you should realize is that your current code really doesn't do anything. it evaluates portions of a field value and compares it to another field in the same table (possibles). unless of course the '[fullname]' syntax actually refers to the 'fullname' field in the "contacts" table, which I guess it's doing huh? If that's the case, then yes, your query is good, but it doesn't cover near what it has to. there are no conditionals that check for the possibilities. that's what is missing.
just to let you know, your first query fails and skips the records because the fullname fields in every record between your 2 tables in your example are not equal. so that's a given. your second attempt fails partially because the instr() related functions are failing on records where there is no comma present in uniSelectedContacts.fullname. the functions are returning values of '0', and thus the records in uniSelectedContacts.fullname that have no comma are being evaluated by this sql criteria:
Code:
WHERE (((possibles.firstname) = Left([fullname], -1)) And
((possibles.lastname) = Mid([fullname], 1)));
that might be irrelevant though, if all the records have at least one comma in them (as it seems to be this way). but even for recs WITH a comma, your last name comparison will fail when middle 'anythings' are present.
but at any rate, again, if what I said at the beginning of the this post is true, you might simply have to call vba to cover the possibilities here. one such solution I can personally come up with might be:
Code:
SELECT possibles.fullname, uniSelectedContacts.addresses,
uniSelectedContacts.cities, uniSelectedContacts.us_states_and_canada,
uniSelectedContacts.zip_codes, possibles.[firstname] AS Expr1,
possibles.[lastname] AS Expr2 INTO PrepareForDuplicateCheck
FROM uniSelectedContacts INNER JOIN possibles ON
uniSelectedContacts.TheName = possibles.fullname
WHERE possibles.firstname = GetFirst([fullname]) And
possibles.lastname = GetLast([fullname]);
You can do it that way, OR...the other option is to simply call one function twice for every record and use the code to analyze the fullname in each of the two 'fullname' fields. If you do it that way, you can simply ignore the middle 'anything' (initial, name, etc...) with regard to comparing the 2 names (first and last).
So, I will give you an example of using 1 procedure. I noticed that the data you posted has the first and last names separated by a comma. I will also assume that these 2 names will ALWAYS be separated by a comma. So let's take your sample data:
Let's say in possibles I have this:
Smith,John
Dough,John B
Ward,Jane Karon
Eggert,Samantha R
In uniSelectedContacts I have this:
Smith,John A 1552 1st Ave
Dough,John 1111 2st Ave
Ward,Jane K 2222 3st Ave
Eggert,Samantha Rachel 3333 1st Ave
The output should be:
Smith,John 1552 1st Ave
Dough,John B 1111 2st Ave
Ward,Jane Karon 2222 3st Ave
Eggert,Samantha R 3333 1st Ave
The common ground between the two tables is obviously the comma, as it always appears between first and last. so, why not use the split() function combined with trim() for comparisons? so in the query, you would have:
Code:
WHERE possibles.firstname = GetNamePart([fullname], "first") And
possibles.lastname = GetNamePart([fullname], "last");
So, 1 function with a varying argument in the second slot. So the function might be something like:
Code:
function GetNamePart(fullname as string, which as string) as string
dim parts() as string 'array needed regardless of arguments
parts() = split(fullname, ",")
SELECT CASE which
case = "first" 'code for first name extraction
GetNamePart = trim(parts(0)) 'this is EASY.
case = "last" 'this is almost as EASY
GetNamePart = iif(instr(trim(parts(1)), " ") > 0, _
left(trim(parts(1)), instr(trim(parts(1)), " ") - 1), _
trim(parts(1)))
END SELECT
end function
You need those criteria functions in the query john, but the other thing you need is a conditional SELECT statement, because from what I can see, you want either the rec out of table1 or table2, depending on which one fits what you want, right? That can't be done through a WHERE clause (easily anyhow). So write another function that returns the most comprehensive of the two 'fullname' fields. Here is what I would go with as the complete solution if I were doing this:
Code:
SELECT GetFinalName(possibles.fullname, uniSelectedContacts.TheName) as FullName,
uniSelectedContacts.addresses,
uniSelectedContacts.cities, uniSelectedContacts.us_states_and_canada,
uniSelectedContacts.zip_codes, possibles.[firstname] AS Expr1,
possibles.[lastname] AS Expr2 INTO PrepareForDuplicateCheck
FROM uniSelectedContacts INNER JOIN possibles ON
uniSelectedContacts.TheName = possibles.fullname
WHERE possibles.firstname = GetNamePart([fullname], "first") And
possibles.lastname = GetNamePart([fullname], "last");
FUNCTIONS NEEDED:
Code:
function GetNamePart(fullname as string, which as string) as string
dim parts() as string 'array needed regardless of arguments
parts() = split(fullname, ",")
SELECT CASE which
case = "first" 'code for first name extraction
GetNamePart = trim(parts(0)) 'this is EASY.
case = "last" 'this is almost as EASY
GetNamePart = iif(instr(trim(parts(1)), " ") > 0, _
left(trim(parts(1)), instr(trim(parts(1)), " ") - 1), _
trim(parts(1)))
END SELECT
end function
function GetFinalName(possible as string, contact as string) as string
dim ptemp as string
dim ctemp as string
'get last part of fullname for both
ptemp = mid(possible, instr(possible, ",") + 1)
ctemp = mid(contact, instr(contact, ",") + 1)
'are middle names or inits present?
if instr(trim(ptemp), " ") > 0 then 'MIDDLE content present
ptemp = mid(trim(ptemp), instr(trim(ptemp), " ") + 1)
else
ptemp = ""
end if
if instr(trim(ctemp), " ") > 0 then 'MIDDLE content present
ctemp = mid(trim(ctemp), instr(trim(ctemp), " ") + 1)
else
ctemp = ""
end if
if ctemp = "" and ptemp = "" then
GetFinalName = contact 'OR possible. if no middle content, return value doesn't matter
else
if len(ctemp) > len(ptemp) then
GetFinalName = contact
else
GetFinalName = possible
end if
end function
I may have over complicated how to get to the end result, and I'm very sorry for the long post, but I do like to tell stories.
The first function too, can be written as a multi-nested IIF() statement right in the query sql, but it's much more readable in vba code. So that part can be simplified. I did not test any of this out, just wrote it by hand, so a few syntax errors may have to be fixed if you want to try these methods. The other thing too, is that it's not advisable to run this sort of complexity on a large dataset. if it's large, you might consider splitting it before using function calls on it.