Brook_Lane
asked on
Looking for assistance with a simple Access Query to select records where AT LEAST one column equals "True".
I'm trying to create what I expect would be a very simple query in Microsoft Access. I've added a screenshot that shows the query for reference. I have one criterion specified the references a date range on a form, which causes the query to select all matches records, which works fine. There are multiple other columns which are true\false that I would like to design the query to select if any one of those has a "true" value. I thought this would be very simple... basically if ANY of the records have a true value for ANY of the columns, then then that record would appear in the results, however all records where there wasn't AT LEAST one true value across all of the columns would be excluded.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Where's your screenshot.... or am I blind?
I specifically chose the sum method because of the way that the QBE will mangle the method Gus suggested. It will work fine but Access will rewrite the expression From:
(a) AND (b or c or d or e)
TO
(a and b) or (a and c) or (a and d) or (a and e)
If there are only a small number of "or" options, this may not be bothersome if you find it annoying, you can prevent this rewrite by NEVER, EVER saving while in QBE view . Sometimes even switching from SQL to QBE view will cause the rewrite. I usually keep a copy of queries with this problem in a module even though I prefer to always use querydefs to hold queries.
(a) AND (b or c or d or e)
TO
(a and b) or (a and c) or (a and d) or (a and e)
If there are only a small number of "or" options, this may not be bothersome if you find it annoying, you can prevent this rewrite by NEVER, EVER saving while in QBE view . Sometimes even switching from SQL to QBE view will cause the rewrite. I usually keep a copy of queries with this problem in a module even though I prefer to always use querydefs to hold queries.
one concern using the SUM() method is that if the columns are not Yes/No columns, but some other data type, then they might also contain NULL values, and when you sum anything + NULL, you get NULL, so if that is the case, you might want to consider
(nz(fld1) + nz(fld2) + nz(fld3) + nz(fld4) + nz(fld5)) <> 0
but I prefer Gustav's method
WHERE ... AND (Field1 OR Field2 or Field3 or Field4)
(nz(fld1) + nz(fld2) + nz(fld3) + nz(fld4) + nz(fld5)) <> 0
but I prefer Gustav's method
WHERE ... AND (Field1 OR Field2 or Field3 or Field4)
Dale,
My suggestion doesn't use Sum(), that would require a properly normalized schema. I also specifically mentioned that ALL columns needed to have a non-null value. I did use the word Sum to describe it but you can't actually use the function since unlike Excel, the Access function sums values in a column rather than columns in a row.
If you are going to use the Nz() function, it is always best to be explicit since the rules are different in VBA than they are in a query. In a query, omitting the ValueIfNull will result in a Zero Length String which is of course a string and therefore not a numeric value.
Nz(fld1, 0) + Nz(fld2, 0) + Nz(fld3, 0), ...
https://support.office.com/en-ie/article/nz-function-8ef85549-cc9c-438b-860a-7fd9f4c69b6c
My suggestion doesn't use Sum(), that would require a properly normalized schema. I also specifically mentioned that ALL columns needed to have a non-null value. I did use the word Sum to describe it but you can't actually use the function since unlike Excel, the Access function sums values in a column rather than columns in a row.
If you are going to use the Nz() function, it is always best to be explicit since the rules are different in VBA than they are in a query. In a query, omitting the ValueIfNull will result in a Zero Length String which is of course a string and therefore not a numeric value.
Nz(fld1, 0) + Nz(fld2, 0) + Nz(fld3, 0), ...
https://support.office.com/en-ie/article/nz-function-8ef85549-cc9c-438b-860a-7fd9f4c69b6c
Pat, good catch on all of the above, and Sum( ) would obviously not work across multiple columns anyway.
I actually have a function fnSum() with sums across a parameter array of columns, so you can include as many columns as you want, and it is configured to ignore NULL values by default. But in this instance, I think I would still prefer to simply use:
WHERE ...
AND (Field1 or Field2 or Field3 or ...)
I actually have a function fnSum() with sums across a parameter array of columns, so you can include as many columns as you want, and it is configured to ignore NULL values by default. But in this instance, I think I would still prefer to simply use:
WHERE ...
AND (Field1 or Field2 or Field3 or ...)
Access will rewrite the expression From:I can't replicate that using Access 365:
(a) AND (b or c or d or e)
TO
(a and b) or (a and c) or (a and d) or (a and e)
and:
SELECT tblA.Id
FROM tblA
WHERE (((([A]) And ([B] Or [C] Or [D] Or [E]))=True));
If Nulls are present, you can still use Nz and straight logic:Where
([YourDateField] Between [Forms]![FormName]![DateFrom] And [Forms]![FormName]![DateTo])
And
(Nz([TrueFalse1], False) Or Nz([TrueFalse2], False) Or Nz([TrueFalse3], False) Or … Or Nz([TrueFalseN], False))
OMG!!! I think MS finally fixed this most annoying "feature.
Access used to change:
THIS:
SELECT tblClass.ClassID, tblClass.ClassTitle, tblClass.ChangedBy
FROM tblClass
WHERE tblClass.ChangedBy = "Pat" AND (tblClass.ClassID =1 OR tblClass.ClassID =2 OR tblClass.ClassID =3 OR tblClass.ClassID =4 OR tblClass.ClassID =5)
TO THIS:
SELECT tblClass.ClassID, tblClass.ClassTitle, tblClass.ChangedBy
FROM tblClass
WHERE (((tblClass.ClassID)=1) AND ((tblClass.ChangedBy)="Pat ")) OR (((tblClass.ClassID)=2) AND ((tblClass.ChangedBy)="Pat ")) OR (((tblClass.ClassID)=3) AND ((tblClass.ChangedBy)="Pat ")) OR (((tblClass.ClassID)=4) AND ((tblClass.ChangedBy)="Pat ")) OR (((tblClass.ClassID)=5) AND ((tblClass.ChangedBy)="Pat "));
If you switched to QBE view and saved, Access rewrote the SQL so it could present it this way:
It still rewrites it to add an excessive number of parentheses
SELECT tblClass.ClassID, tblClass.ClassTitle, tblClass.ChangedBy
FROM tblClass
WHERE (((tblClass.ClassID)=1 Or (tblClass.ClassID)=2 Or (tblClass.ClassID)=3 Or (tblClass.ClassID)=4 Or (tblClass.ClassID)=5) AND ((tblClass.ChangedBy)="Pat "));
Access used to change:
THIS:
SELECT tblClass.ClassID, tblClass.ClassTitle, tblClass.ChangedBy
FROM tblClass
WHERE tblClass.ChangedBy = "Pat" AND (tblClass.ClassID =1 OR tblClass.ClassID =2 OR tblClass.ClassID =3 OR tblClass.ClassID =4 OR tblClass.ClassID =5)
TO THIS:
SELECT tblClass.ClassID, tblClass.ClassTitle, tblClass.ChangedBy
FROM tblClass
WHERE (((tblClass.ClassID)=1) AND ((tblClass.ChangedBy)="Pat
If you switched to QBE view and saved, Access rewrote the SQL so it could present it this way:
It still rewrites it to add an excessive number of parentheses
SELECT tblClass.ClassID, tblClass.ClassTitle, tblClass.ChangedBy
FROM tblClass
WHERE (((tblClass.ClassID)=1 Or (tblClass.ClassID)=2 Or (tblClass.ClassID)=3 Or (tblClass.ClassID)=4 Or (tblClass.ClassID)=5) AND ((tblClass.ChangedBy)="Pat
Have tried simply using a sub-query. A simple select query that selects all rows with the Boolean values true, and then use that as the source of your aggregating query, where, for example, you can now count the rows (or indeed use any other aggregate function you might want)...
TrueQ SQL. The fields y1, y2, y3 are Booleans...
BTW. Why are people complaining about the way Access rewrites queries? What is wrong with parentheses that make things explicit. It just might be the case that Access understands how to compose a query to maximize JET's performance. Can anyone demonstrate away of writing a query by hand that turns out to be significantly faster than the automatically written ones (pass-through queries excepted). Just wondering.
TrueQ SQL. The fields y1, y2, y3 are Booleans...
SELECT Table1.y1, Table1.y2, Table1.y3, Table1.names
FROM Table1
WHERE (((Table1.y1)=True)) OR (((Table1.y2)=True)) OR (((Table1.y3)=True));
Aggregate Query SQLSELECT Count(TrueQ.y1) AS CountOfy1, Count(TrueQ.y2) AS CountOfy2, Count(TrueQ.y3) AS CountOfy3, TrueQ.names
FROM TrueQ
GROUP BY TrueQ.names;
BTW. Why are people complaining about the way Access rewrites queries? What is wrong with parentheses that make things explicit. It just might be the case that Access understands how to compose a query to maximize JET's performance. Can anyone demonstrate away of writing a query by hand that turns out to be significantly faster than the automatically written ones (pass-through queries excepted). Just wondering.
Open in new window