Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Heidi Brebels
23,239 PointsMySQL Query help
I have the following MySQL table: T_Product_Codes
with the following columns: id (autoincrement), productid, code1, code2, code3
1 productid can have several rows in the table, for example:
SELECT productid, code1, code2, code3
FROM T_Product_Codes
WHERE productid = '12345652'
Result:
productid code1 code2 code3
123456 FIXATION PRODUCTTYPE BANDAID
123456 FIXATION LENGTH 33CM
123456 FIXATION WIDTH 5CM
Now, I need to know all the productid's that have those same characteristics as this one. So, I have the productid (123456 in this case). And I need to know which other productid's also have those three code1, code2 and code3 characteristics in this same table. Other products can have more than these three rows, but not less.
That way, I can see which other products could be used in stead of this one, like comparable products.
I can't seem to figure it out on my own ... any help would be greatly appreciated!
Heidi Brebels
23,239 PointsHello Michael,
No, I want to know all the product id's that have the same characteristics as this productid.
For example: I have this product 123456. What other products could I use in stead of this one?
then I would need the following
SELECT DISTINCT productid
FROM T_Product_Codes
WHERE code1, code2, code3 IN (
SELECT code1, code2, code3
FROM T_Product_Codes
WHERE productid = '12345652'
)
only, with this query, it's an OR situation, and I need an AND situation. The comparable products that I want to find, need to have all the same code1, code2, code3 combinations. It can have more combinations, but they need to have at least the ones that this product has.
Ken Alger
Treehouse TeacherHeidi;
I've been working on and thinking about your issue, have you been able to come up with a solution? My other question is regarding how you have designed your T_Product_Codes table and why it is necessary to have multiple entries for the same productid? It doesn't seem to conform to most normalization rules I have seen and am just curious if there is a specific need for your particular table design.
Thanks,
Ken
Heidi Brebels
23,239 PointsHello Ken,
Thanks for still thinking about it!
I first tried a PHP alternative, like this:
//PHP code
//get all different code combinations (code1 code2 code3)
$alternativeproducts = array();
$codecombinations = get_codes_for_id($productid);
if (!empty($codecombinations)) {
//go through every one of the code combinations and see if there is a product that matches it,
// it also has to be a product that was found in all previous code combination matches.
foreach ($codecombinations as $codecombination) {
$alternativeproducts = get_productids_for_codes(trim($codecombination["code1"]), trim($codecombination["code2"]), trim($codecombination["code3"]), $alternativeproducts);
}
}
//PDO query like this
SELECT DISTINCT zi_id
FROM T_Producteigenschappen
WHERE code1 = ?
AND code2 = ?
AND code3 = ?
AND productid IN //all of the previously found productids
But, as you can see, I need to query the database multiple times like this and I don't like that. It's not only extra database load, it's also that PHP will be slower at finding the alternative products than the database would be if I could query it with one query.
But this solutions inspired me today to find this next one. I do still need to query the database twice. Once for the code combinations of the current product and once for the alternative products. But, it feels better already ...
//PHP code:
$codecombinations = get_codes_for_id($productid);
$alternativeproducts = get_comparableproducts_for_codecombinations($codecombinations);
//PDO code
function get_codes_for_id($productid) {
require("_inc/database.inc.php");
$resultarray = array();
try {
$query = "SELECT DISTINCT code1, code2, code3 FROM T_Product_Codes WHERE productid = :productid";
$results = $db_mnet->prepare($query);
$results->bindParam(': productid',$productid,PDO::PARAM_STR);
$results->execute();
} catch (Exception $e) {
//echo "Data could not be retrieved from the database.";
//exit;
}
$resultarray = $results->fetchAll(PDO::FETCH_ASSOC);
return $resultarray;
}
function get_comparableproducts_for_codecombinations ($codecombinations) {
require("_inc/database.inc.php");
$resultarray = array();
try {
if (!empty($codecombinations)) {
$unionallquery = "";
foreach ($codecombinations as $codecombination) {
if ($unionallquery != "") { $unionallquery .= " UNION ALL "; }
$unionallquery .= "SELECT DISTINCT a.productid
FROM T_Product_Codes a
INNER JOIN T_Product_Codes b
USING (code1, code2, code3)
WHERE a.code1 = ? and a.code2 = ? and a.code3 = ?";
}
$query = "SELECT t1.productid
FROM ($unionallquery) t1
GROUP BY productid
HAVING COUNT(t1.productid) = ?";
$results = $db_mnet->prepare($query);
$paramid = 1;
foreach ($codecombinations as $codecombination) {
$results->bindValue($paramid,$codecombination["code1"],PDO::PARAM_STR);
$paramid++;
$results->bindValue($paramid,$codecombination["code2"],PDO::PARAM_STR);
$paramid++;
$results->bindValue($paramid,$codecombination["code3"],PDO::PARAM_STR);
$paramid++;
}
$results->bindParam($paramid,count($codecombinations),PDO::PARAM_INT);
$results->execute();
}
} catch (Exception $e) {
//echo "Data could not be retrieved from the database.";
//exit;
}
$resultarray = $results->fetchAll(PDO::FETCH_ASSOC);
return $resultarray;
}
With UNION ALL, I get all of the products that have one of these code combinations and then in the end, I only want to keep the ones that appear exactly the number of code combinations that my original product had.
What do you think about this solution?
About the design of the table itself. I designed the entire database myself, except for 2 tables. T_Product and T_Product_Codes. T_Product contains all the unique products that are available on the market and T_Product_Codes contains all of their characteristics. We get the contents of these tables every month from a third party. The table looks like this, because that is how we get the content delivered.
In what other way would you design this table to make this query easier? See, I understand that, in an ideal world, all the unique characteristics would be in a separate table. But you would still need that one table that links the unique products with the unique characteristics. And that would be an N to N relationship. So that table with multiple entries of the same productid would still exist ... and my question would still be the same ... Or am I missing something?
Thanks for brainstorming with me!
Regards Heidi
1 Answer
Ken Alger
Treehouse TeacherHeidi;
Is this essentially what you are looking for?
SELECT productId, code1, code2, code3
FROM T_Product_Codes
GROUP BY productId
HAVING code1 = 'a' AND code2 = 'b' AND code3 = 'c';
Where 'a', 'b', and 'c' are the values for which you are looking?
Ken
Heidi Brebels
23,239 PointsHello Ken,
Essentially, yes ... only there are more than one code1, code2, code3 combinations that it should have. And I only need the productId's, but that's a minor thing.
For example, if this is data in the T_Product_Codes:
productid code1 code2 code3
123456 FIXATION PRODUCTTYPE BANDAID
123456 FIXATION LENGTH 33CM
123456 FIXATION WIDTH 5CM
654321 FIXATION PRODUCTTYPE BANDAID
654321 FIXATION LENGTH 33CM
654321 FIXATION WIDTH 5CM
654321 FIXATION FIBERS COTTON
777777 FIXATION PRODUCTTYPE BANDAID
777777 FIXATION LENGTH 33CM
And the product 123456 is chosen. Then I would like to see all the products that have the same characteristics as this productid.
Since product 123456 has:
code1 code2 code3
FIXATION PRODUCTTYPE BANDAID
FIXATION LENGTH 33CM
FIXATION WIDTH 5CM
that would mean that the comparable products for this product would be 654321. Because it has those same 3 code combinations as the given product (123456). It has one more, but that's ok.
Product 777777 does not have all 3 code combinations, so I don't want that productid in this case.
In another example, when product 777777 is chosen, then the comparable products, the ones that I want to get back, will be both 123456 and 654321.
When product 654321 is chosen, there will be no comparable products, because none of the other 2 have the 4 code combinations (code1, code2, code3) that this one has.
Michael Escoto
30,028 PointsMichael Escoto
30,028 PointsIf I'm understanding your question correctly you want to return all rows where the productid is equal to 123456 and code1 equals FIXATION.
You should be able to add an AND to the WHERE statement. So WHERE productid = 123456 AND code1 = 'fixation';