I’ve been looking at this for too long and I’ve have lost all capacity for logic. Pointers/help much appreciated.
I have three tables as below, with the columns that matter.
Table: Categories
+-------+--------------+ | catID | catName | +-------+--------------+ | 1 | somename | | 2 | stringname | | 3 | thirdcat | | 4 | stringcat | | 5 | stringother | | 6 | sixthcat | +-------+--------------+
Table: Products
+-----+------+ | pID | pCat | +-----+------+ | 22 | 1 | | 33 | 1 | | 44 | 7 | | 55 | 9 | +-----+------+
Table: Prodcats
+-----+-------+ | pID | catID | +-----+-------+ | 22 | 2 | | 22 | 6 | | 33 | 3 | | 33 | 5 | | 44 | 3 | | 44 | 6 | | 55 | 5 | | 55 | 6 | +-----+-------+
I have a list of category IDs. I need to use this list to return categories with a particular string in catName.
I want categories added to this list if (from categories):
catName LIKE %string% AND catID IN ($mycats)
Obviously no problem there.
However I also need to return categories 2 and 5 (containing ‘string’) but ONLY if they are related (in prodcats) 2to a product that is in catID 1.
That’s where my head broke.
It may be useful to know the following:
- The IDs in $mycats may or may not occur as pCat in the products table.
- There will only ever be either one or two items in $mycats – if there are two, one will always be a cat whose name contains the string I am looking for, the second one will never be.
EDITED: – added sample table data above and an example below to make this clearer.
An example would be:
$mycats=1,4
I would need to get catID 4 – whose names both contains ‘string’. That’s the easy bit.
BUT I also want to get catID 2 and 5, because they too contains string and although are not in $mycats are attached to a pID in the table prodcats which is in catID 1 in products.
I hope that makes it a bit clearer. It’s like mud to me at this point.
The secondary category ids that are also to be included from your requirement may be expressed as:
Now you just
unionthat with your original query:Notes:
unionremoves duplicates automatically, so no need fordistinct. (union allpreserves duplicates)onclause, because such clauses execute as the join is made, whereas putting the condition in thewherecluase would be executed after all possible joins are made, which means a lot more joins are made. Bottom line: It’s much faster this way