Reputation: 714
I have a database app I'm working on for car products.
I want the returned products results to match the conditions of:
I am using:
SELECT *
FROM `PRODUCTS`
WHERE `MAKE` LIKE '%CHEV%'
AND `CATEGORY` LIKE '%BUMPERS%'
AND `OPTIONS` LIKE '%TOW HOOKS%'
OR `OPTIONS` LIKE '%LIGHT MOUNT HOLES%'
When I use this it works but it is producing results from different MAKES as well. So it is returning products from lets say FORD as well... I don't want that.
I want the MAKE and CATEGORY to be strict (they must match) but the OPTIONS can be one or both - or maybe even three or four different options - but at least one option must match.
The OPTIONS
filed is a string separated by pipe characters i.e. LIGHT MOUNT HOLES|TOW HOOKS|FOUR DOOR
, and I don't want to change this.
If I use the above query with just one OPTION in the search:
AND `OPTIONS` LIKE '%TOW HOOKS%'" or just "AND `OPTIONS` LIKE '%LIGHT MOUNT HOLES%'
... it works perfectly. However, if I try to search for multiple OPTIONS, it starts bringing back products from different MAKES.
I have also tried:
SELECT *
FROM `PRODUCTS`
WHERE `MAKE` LIKE '%CHEV%'
AND `CATEGORY` LIKE '%BUMPERS%'
OR `OPTIONS` LIKE '%TOW HOOKS%'
OR `OPTIONS` LIKE '%LIGHT MOUNT HOLES%'
And have the same problem of multiple MAKES showing up.
Upvotes: 3
Views: 43300
Reputation: 2721
SELECT *
FROM `PRODUCTS`
WHERE `MAKE` LIKE '%CHEV%'
AND `CATEGORY` LIKE '%BUMPERS%'
AND (`OPTIONS` LIKE '%TOW HOOKS%'
OR `OPTIONS` LIKE '%LIGHT MOUNT HOLES%'
OR ...)
This will match at least one option.
If you also want to return cars with NO options matched use:
SELECT *
FROM `PRODUCTS`
WHERE `MAKE` LIKE '%CHEV%'
AND `CATEGORY` LIKE '%BUMPERS%'
Edit
Explanation: the difference between this and what you have is that all the LIKE clauses are grouped together. Which means that they are in essence just one condition next to the make and the category. the thing you need to get your head around is that logical AND/OR are not the same as we use them in English. In your query if a car had options like '%LIGHT MOUNT HOLES%' then the condition is met.
Let M (make), C (category), O1 (option1), O2 (option2) denote the 4 clauses you have in your query, and R be the result of evaluating them. Then R = M AND C AND O1 OR O2. if O2 is true, then M, C and O1 are irrelevant. becuase by definition X = A OR B is true if either A or B is true. what you want is R = M AND C AND (O1 OR O2 OR ...). this way R is true only if all of M, C and at least one of the Os is true.
Upvotes: 7
Reputation: 1300
My educated guess would be that it is the fault of the OR
, because it evaluates like (this AND that AND that AND that) OR something
. You could confirm that by checking if all returning different makes contain the criteria from the OR
.
As for solving it: You can use brackets: this AND that AND (that OR something_else)
.
Upvotes: 1
Reputation: 324630
What you are doing is comparable to having:
3 * 4 + 5
and expecting 27
. But because of the order of precedence of operators, the answer is 17
.
You can "fix" this and get 27
like so:
3 * (4 + 5)
The exact same applies to many programming languages, and MySQL is no exception.
Put your OR
options in parentheses so they get treated as a group.
Upvotes: 3