Dear Stephanie:
I feel your pain.
Any time your database has 2 ways to represent the same thing, there is the
danger that the data will have rows that represent that same thing in
contradictory ways. It is my interpretation of a certain rule of database
design that this must be avoided. Early in this thread I tried to point
this out when I was recommending you drop the Boolean (yes/no)
PrimaryFamilyNumber. I now recommend you search to find out how prevalent
this problem is. The problem occurs whenever PrimaryFamilyMember is False
and the SignificantOtherID = ContactID, or when PrimaryFamilyMember is True
and SignificantOtherID <> ContactID. Do you agree with that?
Assuming you do, you should be able to derive the value now in
PrimaryFamilyMember by testing whether SignificantOtherID = ContactID. Do
you see now that this theme has permiated what I wrote you previously? And
do you see that this is at the core of your problem? I think you do, and
the light has just come on. Good!
Obviously, then, this is why my solution has not been working for you.
These are inconsistencies in the data that I expected all along may cause
just this problem!
I don't intend to "rub it in, now" but I am feeling a bit vindicated in my
opinions expressed earlier. Mostly, I'm just glad the light has come on for
you! However, with the data in its current state, neither of us can proceed
to perform what you originally requested, which was to sort everything so
John and Mary are sorted adjacent, with John first. I'm just trying here to
keep the target in mind.
You should not eliminate the PrimaryFamilyMember at this time, not until you
have made SignivicantOtherID to be consistent with it. I believe it is
likely that in most, if not all, cases where the inconsistency exists
PrimaryFamilyMember has been set correctly and SignificantOtherID needs to
be changed. Do you agree?
I do not know any better way to work this out than to prepare the query I
gave above to show all these inconsistencies so someone can go to work on
them to eliminate the problem, in most cases by setting the correct
SignificantOtherID. Once this is repaired, you can quit using
PrimaryFamilyMember in all new work, and you can remove it from your form.
You do not have to remove it from your table, indeed, you should not do this
until you have removed any existing code that still uses
PrimaryFamilyMember. Doing so would break that code.
The other thing needed would be to modify your form(s) that allow adding new
members, or changing SignificantOtherID, so that the value of
PrimaryFamilyMember is set correctly and automatically whenever such changes
are made. I believe the BeforeUpdate event is adequate for this.
Why John shows up twice is the next problem to address. I'm thinking this
is a JOIN problem in there somewhere. That means finding in which of the
related tables are there 2 rows matching the relationship specified in the
JOIN . . . ON portions of your query. My first guess is DuesLineItem. Do
you have two of these for John's ContactID. If so, do you want to show both
of them, only one, or aggregate them? These are the only simple choices.
The answer will depend on the context of the uses you intend for this query.
So, that will be up to you.
I hope I'm not suddenly seeming to be overbearing. Actually I'm quite
pleased that you've discovered what I have been trying to say for a while.
The problem is one I expected from early on. My poor powers of persuasion
and explanation just couldn't convey what I needed to say, but you found it
out for yourself in spite of this. Good Job! I'm happy for you.
Well, the pressure to answer my questions is only in that they are a
prerequisite to having my help, if help it is. If it is helping, I'm
satisfied that you think so. You also have the option to start a new thread
and ask your questions again, asking me to butt out. Others here are quite
capable of steering you through this maze. I would never bear a grudge if
you did so. Anyway, I hope the pressure is the result of your desire to
obtain my assistance, and that's the natural price for it. Unless I'm
informed, I can't really help. I ask the questions I need to ask in order
to try to be of assistance. You answer them only if you are finding that
assistance worth your time, effort, and frustration. So, no hard feelings
either way!
Or, I ask questions to try to get you to look in the right place to find the
source of your difficulty. That was probably my motivation in this case.
Looking at the questions in my previous post, were they not exactly the ones
needed to guide you to the problem you have now discovered? Were they not
what led you to your epiphany? I'm hoping so, that I may have played a
small part in guiding you to where you are now, which is exactly where I
wanted you to be, given the assumptions I have had all along.
Tom Ellison
Stephanie said:
Tom,
The pressure to answer your questions correctly! And execellent question
it
is, because I think I see the problem.
Susie's BaseName is Susie Anderson, but her SignificantOtherID points to
herself and not John Doe.
John's BaseName is John Doe, and his SignificantOtherID points to himself
and not Susie Anderson.
And strangley, John Doe shows up in the query results twice- each time
pointing to himself as the SignficantOtherID.
I know that this query below uses PrimaryFamilyMember which we are trying
to
do away with in favor of SignificantOtherID, but it does bring back the
correct BaseName, ContactID and SignificantOtherID (if that helps):
SELECT Nz(c1.NickName,c1.FirstName) & " " & c1.LastName AS [Member Name],
IIf(PrimaryFamilyMember,[Member Name],(SELECT Nz(c2.[NickName],
c2.[FirstName]) & " " & c2.[LastName] FROM Contacts c2 WHERE
c2.ContactID =
c1.SignificantOtherID)) AS [Base Name], C1.FirstName, C1.LastName,
C1.ContactID, C1.SignificantOtherID
FROM (PaymentTypes INNER JOIN (DuesItemType INNER JOIN (Contacts AS C1
INNER
JOIN (DuesLineItem INNER JOIN tblDuesRates ON DuesLineItem.DuesRateID =
tblDuesRates.DuesRateID) ON C1.ContactID = DuesLineItem.ContactID) ON
DuesItemType.DuesItemTypeID = DuesLineItem.DuesItemTypeID) ON
PaymentTypes.TypeID = DuesLineItem.TypeID) INNER JOIN MemberCategory ON
C1.MemberCategoryID = MemberCategory.MemberCategoryID;
Couldn't I just make PrimaryFamilyMember default to "yes" and be invisible
unless SignificantOtherID is not null, and then show PrimaryFamilyMember
so
the user could uncheck as appropriate? Thanks for your help!
Tom Ellison said:
Dear Stephanie:
So, what did Susie's BaseName turn out to be? Is her SignificantOtherID
NULL? Is it set to the ContactID of John?
Please carefully confirm your facts. I need to know whether there is a
problem in the code, and what that might be, or if the data is not as
expected. I could probably offer some adjustment with this knowledge,
but I
don't have the database in front of me, as you do. I must rely on you to
thoroughly and carefully investigate the cause of your difficulty. All I
can do is give hints!
Tom Ellison
Tom,
I apologize for the delayed response and appreciate you hanging in
there!
I have this query that I've called DuesByMemberBase:
SELECT IIf(SignificantOtherID Is Null,c1.[LastName] & ", " &
Nz(c1.NickName,c1.FirstName),(SELECT c2.LastName & ", " &
Nz(c2.NickName,
c2.FirstName)
FROM Contacts c2 WHERE c2.ContactID = c1.SignificantOtherID)) AS
[BaseName]
FROM Contacts AS c1;
This does bring back a Base Name for each person. However, I expected
Susie
Anderson's BaseName to be John Doe, because I want to be able to add
together
Susie and John's "bucks". Anyway, I've named the query for ease
(expect I
can't quite figure out how to use it within a second query as the only
field
name available is BaseName).
And I couldn't get the sorting part to work- there was a syntax error
that
I
can't figure out. Thanks for the help!
:
Dear Stephanie:
The query I posted was intended only to illustrate how to get the
BaseName.
Does it get the BaseName correctly? If you want the "together" you
would
need to sort by that:
SELECT *,
IIf(SignificantOtherID IS NULL,
c1.[LastName] & ", " & Nz(c1.NickName, c1.FirstName),
(SELECT c2.LastName & ", " & Nz(c2.NickName, c2.FirstName)
FROM Contacts c2
WHERE c2.ContactID = c1.SignificantOtherID) AS [Base Name]
FROM Contacts c1
ORDER BY
IIf(SignificantOtherID IS NULL,
c1.[LastName] & ", " & Nz(c1.NickName, c1.FirstName),
(SELECT c2.LastName & ", " & Nz(c2.NickName, c2.FirstName)
FROM Contacts c2
WHERE c2.ContactID = c1.SignificantOtherID),
SignificantOtherID
I would prefer we get just this much straight before we leap too far
ahead.
Does this work as far as giving the correct BaseName and sorting them
the
way you want?
I had intended to use this much:
SELECT *,
IIf(SignificantOtherID IS NULL,
c1.[LastName] & ", " & Nz(c1.NickName, c1.FirstName),
(SELECT c2.LastName & ", " & Nz(c2.NickName, c2.FirstName)
FROM Contacts c2
WHERE c2.ContactID = c1.SignificantOtherID) AS [Base Name]
FROM Contacts c1
as a building block on which to build. It is not important whether
this
sorts correctly. Rather, save this much as a separate query and use
it
instead of the Contacts table to build the final query. Sorting can
wait
till the final step, although it can be good to see ahead of time that
it
will sort correctly.
Tom Ellison
Tom,
Thanks for your thoughtful reply.
I am certainly willing to get rid of PrimaryFamilyMember flag as
long
as I
can get the query to return the data I want. The query posted isn't
doing
what I had hoped.
John Doe and Susie Anderson have a family membership. John Doe is
"primary"
so I want his name to be BaseName (if I get rid of "primary", I
still
want
one in the couple to be the BaseName, not both of them). When Susie
has
cashed-in bucks, I need to relate them to the BaseName. The query
that
you
posted does not keep all of their information together. In my
query, I
select Doe, John as the BaseName and want to see all of the payments
associated with that family membership. The posted query does not
return
Susie's information with John's. Rather I have to run the query
again
with
Anderson, Susie as the BaseName which means that my report will not
gather
the data from both John and Susie to give me a snapshot of their
family
membership. That's why I want one (either John or Susie to always
be
the
BaseName).
The query I''m posting gives me what I want- expect that I'm still
using
PrimaryFamilyMember and that I can't get the report to state that
the
information is from both John and Susie (If I put on the report to
list
BaseName, Susie's name- correctly- doesn't appear, but I would like
her
name
listed as she is the SignificantOtherID associated with John.
However,
John
is the SOID associated with Susie....).
SELECT Year([DateCreated]) AS [Date Year],
IIf([PrimaryFamilyMember],[c1].[LastName] & ", " &
Nz([c1].[NickName],[c1].[FirstName]),(SELECT c2.[LastName] &", " &
Nz(c2.[NickName], c2.[FirstName]) FROM Contacts c2 WHERE
c2.ContactID
=
c1.SignificantOtherID)) AS [Base Name], C1.PrimaryFamilyMember,
C1.FirstName,
C1.LastName, C1.ContactID, Dues.DuesAmount, C1.SignificantOtherID,
DuesLineItem.Reference, DuesLineItem.Amount,
DuesLineItem.DateRemitted,
DuesLineItem.DateCreated, PaymentTypes.Type,
DuesItemType.DuesItemType,
Dues.MemberCategory
FROM PaymentTypes INNER JOIN (DuesItemType INNER JOIN (Contacts AS
C1
INNER
JOIN (DuesLineItem INNER JOIN Dues ON DuesLineItem.DuesRateID =
Dues.DuesRateID) ON C1.ContactID = DuesLineItem.ContactID) ON
DuesItemType.DuesItemTypeID = DuesLineItem.DuesItemTypeID) ON
PaymentTypes.TypeID = DuesLineItem.TypeID