PHP MySQL select array in array - php

I have a field in my database that is an array ie: id_ingredients = "1,8,3,9,5,2,7,4"
I want to compare a variable that is also an array to give a result if any of the variable ids exist in the field ids.
I am trying to check to see if a product's ingredients contain any of the ingredients in the variable. If someone is allergic to nuts for example i want to selet all products that contain nuts of any kind. So i query my ingredients to get the id of any ingredient that has the word "nut" in its name. Then i need to get the products with any of the ingredient ids.
This is what I have...
$alg = $_POST['alg'];
mysql_select_db($database, $Products);
$query_availIngredients = "SELECT * FROM ingredients WHERE ingredient LIKE '%$alg%' ";
$availIngredients = mysql_query($query_availIngredients, $Products) or die(mysql_error());
$row_availIngredients = mysql_fetch_assoc($availIngredients);
$ingarray = array();
do{
$ingarray[] = $row_availIngredients['id'];
} while ($row_availIngredients = mysql_fetch_assoc($availIngredients));
$alg = implode (',', $ingarray);
mysql_select_db($database, $Products);
$query_Products = "SELECT *FROM products WHERE
id_ingredients LIKE '%$alg%' " ;
$Products = mysql_query($query_Products, $Products) or die(mysql_error());
$row_Products = mysql_fetch_assoc($Products);
Thank you in advance for your help.

Placing an array of IDs in a single database field isn't really a good idea and you lose some of the power a relational database gives you by designing your database this way.
Rather than storing an array of ingredient IDs in your product's table I would create a third table.
An example table schema would be like this:
Products
id
productName
productDescription
Ingredients
id
ingredientName
ProductIngredients
id
id_Products
id_Ingredients
Some sample data might look like:
Products
id productName productDescription
1 Peanutbutter And Jelly Sandwich Best sandwich ever
Ingredients
id ingredientName
1 Peanutbutter
2 Jelly
3 Special sauce
4 Bread
ProductIngredients
id id_Products id_Ingredients
1 1 1
2 1 2
3 1 4
You could then get a list of IDs of ingredients containing the word 'nut' like this:
SELECT id FROM Ingredients WHERE ingredientName LIKE '%nut%'
And a list of products containing ingredients which contain the word 'nuts' like this:
SELECT
Products.productName
FROM
Products
LEFT JOIN ProductIngredients ON ProductIngredients.id_Products = Products.id
LEFT JOIN Ingredients ON Ingredients.id = ProductIngredients.id_Ingredients
WHERE
Ingredients.ingredientName LIKE '%nut%'
You could get a list of ingredients for a product like this:
SELECT
Ingredients.ingredientName
FROM
Ingredients
LEFT JOIN ProductIngredients ON ProductIngredients.id_Ingredients = Ingredients.id
WHERE
ProductIngredients.id_Products = 1
This would give you a list such as this:
Peanutbutter
Jelly
Bread
Edit
This is is called a many-to-many relationship.

Related

PHP & Mysql - nested loop

I have 2 tables - products and productimages.
product has unique id and title.
productimages has productid and imageurl. these are examples of my tables:
products:
|id|title |
_____________
|1 |Laptop |
|2 |Speakers |
productimages:
|productid|imageurl|
___________________
| 1 |lap1.png|
| 1 |lap2.png|
| 1 |lap3.png|
| 2 |spe1.png|
Right now I have a nested loop in PHP.
loop through all rows of -> select * from products
and for every product inside the loop -> select * from productimages where productid = id which is basically another loop inside the first loop.
and then I take all productimages into array and decode to JSON [title,photos].
Now imagine you have 2 million rows in productimages, the query times are too high, is there any way to make it more efficient?
$query = "SELECT * FROM products ORDER BY id LIMIT 10;
$result = mysqli_query($con,$query);
if(mysqli_num_rows($result)>0)
{
$response = array();
while($row = mysqli_fetch_assoc($result)) {
$photos = array();
$id = $row["id"];
$title = $row["title"];
$queryp = "select imageurl from productimages where productid= '".$id."';";
$resultp = mysqli_query($con,$queryp);
if(mysqli_num_rows($resultp)>0)
{
while($row2 = mysqli_fetch_assoc($resultp)) {
$photourl = $row2["imageurl"];
array_push($photos,$photourl);
}
}
}
}
Some betterment for you could be:
1) Don't use select *. Use column names instead. e.g. select products.id, products.title, productimages.imageurl
2) Use JOIN instead of nested loop
So, you can try querying data like:
select products.id, products.title, productimages.imageurl
from products
join productimages on products.id = productimages.productid
ORDER BY products.id LIMIT 10
This case is not uncommon - you have two tables in a one to many relationship.
You should never nest an SQL call in a loop if you can possibly avoid it but there is a decision to be made about one SQL call or two.
A single SQL call could be:
SELECT id, title, imageURL
FROM products LEFT JOIN productImages ON id=productid
The disadvantage of this is that you are extracting the title several times for each product and this is wasteful.
Using two SQL statements you can download the titles once for each product:
SELECT id, title FROM products
The results of this query can be stored in an associative array - so that you can look up the title for each id.
The second query is:
SELECT productid, imageURL FROM productImages ORDER BY productid, imageURL
You can loop through the results of this query, spitting out the title as you go.
To save the images with product you can add a column imageurl in the products table.collect the image names with , and insert that image name string to the products table.
your table looks like below.
+--------------+--------------+---------------------------+
| id | title | imageurl |
+--------------+--------------+---------------------------+
| 1 | Laptop | lap1.png,lap2.png,lap3.png|
+--------------+--------------+---------------------------+
| 2 | Speakers | spe1.png |
Hope you understood what i explain.

Only get one occurance of a table row in mysql php based on id

I have a table that looks like this
id | itemID | catID | Title
----------------------------------------------------------------------------
0 3 4 Hello
1 3 6 Hello
2 4 4 Yo
3 4 8 Yo
4 5 2 Hi
5 1 3 What
I want to do a MySQL PHP Select that only gets one occurrence of the itemID. As you can see they are the same item, just in different categories.
This is what I tried
SELECT * FROM Table GROUP BY itemID
That didn't seem to work, it still just shows duplicates.
Is this what you are looking for? http://www.sqlfiddle.com/#!2/5ba87/1
select itemID, Title from test group by itemID;
As far as MySQL is concerned, the data is all unique, since you want all of the columns. You have to be more specific.
Do you just want the itemID (or other column)? Then say so:
select [column] from Table GROUP BY itemID
Do you want the last entry of a particular item ID? Then say that:
select * from Table where itemID = 1 ORDER BY id DESC
Or the first one?
select * from Table where itemID = 1 ORDER BY id
If none of these are what you want, then you probably need to restructure your tables. It looks like you want different categories for your items. If so, then you'll want to split them out into a new join table, because you have a many-to-many relationship between Items and Categories. I recommend reading up on database normalization, so you're not duplicating data (such as you are with the titles).
If you want everything for the distinct itemIDs, you could certainly take a long route by doing one selection of all of the distinct itemIDs, then doing a series of selections based on the first query's results.
select distinct(`itemID`) from Table
Then in your PHP code, do something like this:
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
$itemID = $row['itemID'];
$sql2 ="SELECT * FROM Table WHERE 1 and `itemID`=\"$itemID\" limit 1";
$result2 = #mysql_query($sql2, $connection);
while ($row2 = mysql_fetch_array($result2))
{
$id = $row2['id'];
$itemID = $row2['itemID'];
$catID = $row2['catID'];
$Title = $row2['Title'];
}
}

select all users where count() equals a specific value

$sql = "SELECT * FROM cars WHERE COUNT(brand)='4'";
$results = mysql_query($sql);
$rows = mysql_fetch_array($results);
print_r($rows);
the table cars has these columns:
id brand price
0 bmw
1 corvette
2 mercedes
3 bmw
4 bmw
5 toyota
6 bmw
7 honda
8 lotus
this is what I am trying to do, return from the table 'cars' every brand that has 4 different cars. In this example bmw has 4
4 different cars is 4 different rows with the same brand name.
so I am trying to echo the name of the brand where the total number of inventory is 4.
I hope I made sense, any help would be appreciated.
EDIT: I tried
SELECT * FROM cars LEFT JOIN users ON cars.user_id=users.user_id HAVING count(user_id) = 4 this is not working any ideas?
SELECT brand FROM cars GROUP BY brand HAVING COUNT(brand) = 4
For you edit:
SELECT t1.brand, t2.email
FROM cars t1
LEFT JOIN users t2 ON t1.user_id = t2.user_id
GROUP BY t1.brand HAVING COUNT(t1.brand) = 4
I think in the query like you have you need to use having
SELECT * FROM cars HAVING COUNT(brand)=4;
and group by depending on what you grouping
You want perform an aggregate function (COUNT) on multiple rows at once. Pretty much anytime you want to perform multiple counts, you should think GROUP BY.
$sql = "SELECT brand FROM cars GROUP BY brand HAVING COUNT(*) >= 4";
If you do SELECT * in this query, you'll get 1 random row for each brand (probably the one with the lower id).
The HAVING clause will act as a WHERE on each of the groups.

help on arranging my sql data (products grouped within categories

I am tring to display all my products within their category, so something like:
Category Name1
Product Name1, Product Name2 ...
Category Name2
Product Name3, Product Name4 ...
I am using oscommerce, So the database structure is not my choice. The database tables I need to use are
products_to_categories: holds the products_id and categories_id
products_description:holds products_id and products_name (other info in this table are not important)
category_description: holds the categories_id and categories_name
I have tried everything and i only can get to echo the products (all together) and categories all together, but I can't get them in a way that all the products within a category sit under the specified name
As I said everything I tried resulted in a way that simply echoed all the categories AND THEN all the products
I really hope you can help
thanks
There are two ways of approaching this, and the idea behind is was already given as an answer here, by Zod.
The first way is using category_description to get all categories (whether it's full of products or not), the second way is to only extract categories that are used (i.e., not getting a complete list of categories). I'll go through the first way; getting all categories.
Run through category_description, and get the IDs and category names into an Array.
Now, run through that array with foreach and grab all product_ids from products_to_categories. (SELECT products_id FROM products_to_categories WHERE categories_id=[CATEGORY ID GOES HERE]).
Now that you have your product IDs that are associated with the concurrent category, you can run through the products_description and get their name. Essentially, your code should look like:
foreach ($categories as $category) {
...display category name and run code to get product ids...
foreach ($products as $product) {
...get product name from products_description...
...display product name...
}
}
I dont understand fully how you want to display. I hope you like to display like this
Category Name1
Product Name1
Product Name2
Category Name2
Product Name3
Product Name4
Easiest way i think, get distinct list of category in an array.
with cat id and cat name
Loop that array and print products for each Category.
If category list is huge storing it in array and looping will be a bad idea.
You'll likely need a LEFT JOIN in your SQL, to merge the three tables together, and order the query by category_name, product_name.
Something like:
SELECT p.product_id, p.product_name, c.category_name FROM `products_description` p
LEFT JOIN `products_to_categories` linker ON linker.product_id=p.product_id
LEFT JOIN `category_description` c ON linker.category_id=c.category_id
ORDER BY c.category_name, p.product_name
Then your PHP to output the list would be something like:
$data = array(); // Data from query above
$cur_category = '';
foreach($data as $product) {
if ($product['category_name'] != $cur_category) {
// Category changed; display it
echo $product['category_name'].": ";
$cur_category = $product['category_name'];
}
echo $product['product_name'].", ";
}

PHP/MySQL: Check if something 'belongs-to' something else?

I have two tables: Stores and Items. The relationship is: Stores 1---* Items
In PHP/MySQL what would be the best (fastest/simplest) way to check if a particular item belongs to a particular store.
In other words given for example:
$store_id = 1;
$item_id = 12;
I want to check if item 12 belongs to store 1 (and not some other store).
I usually do a select on Items matching both the store_id and item_id and limit the results to 1. Then check how many rows (0 or 1) were returned with mysql_num_rows. Is there a better way?
Update:
Both tables have an "id" column. The Items table has a "store_id" column.
SELECT COUNT(*) AS count
FROM stores JOIN items USING(store_id)
WHERE item_id = 12
AND store_id = 1
Then you'd get the results, and check of count > 0 or not. However, if I'm getting your DB design right, then you have a very messed up database.
From what you describe, an item can only exist in one store. So my guess of the general layout here would be like this:
STORE ITEM
----- ----
store_id ---| item_id
store_name |--- store_id
... item_name
...
Is this correct? An item can never exist except in the one store? So if it's a screwdriver, every store would need a different item_id to hold it?
A better design would be:
STORE STORE_ITEM ITEM
----- ---------- ----
store_id ------- store_id |------ item_id
store_name item_id ---| item_name
... ...
With a query of
SELECT COUNT(*)
FROM store JOIN store_item USING(store_id)
JOIN item USING(item_id)
WHERE store_id = 1
AND item_id = 12
Both tables have an id, Items has a store_id
SELECT COUNT(*) FROM Items WHERE store_id = $store_id AND id = $item_id
$r = mysql_query("select NULL from Item where storeID = '$store_id' and ItemID = '$item_id'");
if (mysql_fetch_row($r))
{
it belongs...
}
For fun, I'll throw in a one-liner check:
// if item belongs to store
if (current(mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM Items WHERE store_id = $store_id AND id = $item_id"), MYSQL_NUM)))) {
// it belongs!
}

Categories