PHP MySQL inventory likeness percentage - php

Edit:
I removed the confusing stuff and I wanted to simplify what I want to accomplish:
Let's say John had 2 baskets and 1 of them contained 1 stone, 2 marbles and 2 sticks, the other one contained 2 stones and 2 sticks.
Eric had 1 basket which contained 3 bottles, 2 caps and 1 stone.
Meanwhile Jack had 1 basket which contained 1 stick. Also, Jack has a stone somewhere but it's not inside his basket yet.
For the purpose of this query, let's say we're focusing on Jack's items. So we would go over everybody's baskets and see which basket looks pretty much the same as all the items he has overall (a) without thinking whether Jack's items are inside a basket or not and (b) only compare to Jack's items with items that are inside other people's baskets, not outside.
This would be the ideal end result when searching which baskets Jack can match the easiest with all his items regardless of where his items are currently:
Fact:
Jack has in total 1 stick and 1 stone.
Result:
1st: John's second basket containing 2 stones and 2 sticks
2nd: John's first basket containing 1 stone, 2 marbles and 2 sticks
3rd: Eric's basket containing 3 bottles, 2 caps and 1 stone

This will do what you asked for a single basket:
SELECT SUM(item.qty/(SELECT sum(qty) total FROM basket WHERE bid = xxx)
* 1/all_item.qty) likeness, basket.bid, all_basket.bid all_bid
FROM basket JOIN item USING (bid)
LEFT JOIN
(basket all_basket JOIN item all_item USING (bid))
USING (iid)
WHERE basket.bid = xxx
GROUP BY basket.bid, all_basket.bid
ORDER BY likeness DESC
It's probably possible to join this to the users table to do all his baskets at once. Then wrap it in yet another query to find the best match.
Try this first, and let me know if it works. If it does I'll see if I can do that part tomorrow.

Whilst I'm not sure that there's a simple way to calculate basket likeness as a percentage using SQL, I assume you are simply trying to product product recommendations.
You could formulate a query to produce product recommendations based on the current basket. You can do this by:
Finding any basket that contains at least one item from the current customer's basket.
Limiting the results to products that are in the same category.
You can fetch the appropriate information with the following query:
SELECT b1.basket_id, b1.product_id, b1.quantity, p1.product_category FROM baskets b1
INNER JOIN products p1 ON p1.product_id = b1.product_id
WHERE b1.product_id IN
(
SELECT b2.product_id FROM baskets b2
INNER JOIN products p2 ON p2.product_id = b2.product_id
WHERE b2.basket_id = $basket
AND p2.product_category = p1.product_category
)
AND b1.basket_id != $basket;
This will return the basket ID, product ID, quantity and product category ID for all items in all other baskets that share at least one product with your selected basket. It also filters the results so that the suggested products are always in the same category as the source product.
Here's a sample:
baskets table:
basket_id | product_id | quantity
1, 2, 1
1, 1, 2
1, 3, 5
2, 5, 1
2, 6, 1
3, 1, 1
3, 2, 1
3, 4, 1
products table:
product_id | product_name | product_price | product_category
1, 'cat1 prod1', 14, 1
2, 'cat1 prod2', 1.5 1
3, 'cat1 prod3', 2, 1
4, 'cat2 prod1', 22, 2
5, 'cat2 prod2', 6, 2
6, 'cat2 prod3', 45, 2
7, 'cat3 prod1', 24, 3
8, 'cat3 prod2', 55.4, 3
9, 'cat3 prod3', 22, 3
result of query:
basket_id | product_id | quantity | product_category
3, 1, 1, 1
3, 2, 1, 1
Hopefully that's of some use to you.

Related

Not getting required result after joining 2 tables

I have a view where i need to get list of all dishes from menu table according to main_menuid for a particular user, But here i need to put some conditions
Currently i am using 3 tables for the entire process (table view for all 3 is given at the end)
1) main_menu
2) menu
3) cart
1) I need to get list of dishes according to main_menuid
so here if i need a list of dishes below MM1, so list of dishes that i should get from menu table is (main_menuid is the id of main_menu table)
id main_menuid dish
1 1 D1
2 1 D2
3 1 D3
code i used to get the above data is
$sql = "select * from menu where main_menuid = '".$mainmenuid."'";
$result = mysqli_query($con, $sql);
if (mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_assoc($result))
{
print_r($row);
}
}
2) i will also have a userid with me so now i need to display the above list to a particular user (Let the userid be "1"), but if he already has added any of the above product to cart earlier then it's quanity should also get fetched from cart and for rest of the items(that are not added by him to the cart but is present in the above list) the quantity will be null, so the resulting view should be like this (menuid is the id of menu table)
id main_menuid menuid dish quantity userid
1 1 1 D1 3 1
2 1 1 D2 2 1
3 1 1 D3 0 1
code that i tried for the above result is (but it didn't gave me the desired result)
SELECT menu.main_menuid, menu.dish, cart.userid,
cart.quantity
FROM menu
LEFT JOIN cart ON menu.id=cart.menuid
WHERE main_menuid = '".$main_menuid."' and userid = '".$userid."'
Below is a sample view of all the tables that are being used in the above process
main menu
id mainmenu_name
1 MM1
2 MM2
3 MM3
4 MM4
menu
id main_menuid dish
1 1 D1
2 1 D2
3 1 D3
4 2 D4
5 3 D5
6 4 D6
cart
id userid menuid dish main_menuid quantity
1 1 1 D1 1 3
2 1 2 D2 1 2
3 2 1 D1 1 3
can anyone please tell how to achieve the desired result (DBMS: mysql)
move userID to the join as it is eliminating the null values generated from the left join.
SELECT menu.main_menuid, menu.menuid, menu.dish, cart.userid,
cart.quantity
FROM menu
LEFT JOIN cart ON menu.id=cart.menuid
and userid = '".$userid."'
WHERE main_menuid = '".$main_menuid."'
However this implies you want some dishes not associated to the user so userID will be NULL in some cases.
Why does this work and not in the where clause? Because the filter is applied BEFORE the join. This allows the null values which would occur as a result of the left join to remain.
You can't get userid from your cart table directly, if the desired menu item is not in cart. So your WHERE clause filters out these records. Try this request:
SELECT menu.main_menuid, menu.menuid, menu.dish, IF(ISNULL(cart.userid), ".$main_menuid.", cart.userid) AS userid,
IF(ISNULL(cart.quantity), 0, cart.quantity) AS quantity
FROM menu
LEFT JOIN cart ON menu.id=cart.menuid
WHERE menu.main_menuid = '".$main_menuid."'
I think the problem is on the LEFT JOIN. You should do this way:
LEFT JOIN cart ON menu.id=cart.menuid and cart.dish = menu.dish
EDIT
When you do this way, the userid column will be null at the last line, to avoid this, on select you should put something like this:
SELECT menu.main_menuid, menu.dish,
COALESCE(cart.quantity, 0), -- will put 0 when null
COALESCE(cart.userid, '".$userid."') as userid -- will put '".$userid."' when null

How to query a Sum using an array with duplicate data?

I currently have an Array in PHP with product numbers. Lets call that products.
In my database I have a table containing combinations of product numbers and the price that belongs to that product.
Problem: My Array can hold duplicate entries if for instance article #1 is ordered twice.
If I use a query like
SELECT SUM(price) FROM articles WHERE article_number IN (products)
the duplicate entry of 1 get discarded. The query I am looking for gives the sum of 10 + 10 + 12.5 + 9.95.
Is there a way to do this within MySQL?
As a clarification to my data:
products = [1, 1, 2, 3];
articles| article_number | price
__________________________________
| 1 | 10.0
| 2 | 12.5
| 3 | 9.95
Thank you :)
winmutt has a solid answer. However, if you don't have such a table to to join with then you could build your query like so:
select sum (p) from (
(select price as p from articles where article_number = 1)
union all
(select price as p from articles where article_number = 1)
union all
(select price as p from articles where article_number = 2)
union all
(select price as p from articles where article_number = 3)
) s
If your products were in a table you could do a simple JOIN:
SELECT SUM(price) FROM articles JOIN products on article_number=product_number
I thought there might be an easier way of doing this in SQL. I solved it in PHP by querying all the prices of the array's products and then in iterating over my Array in PHP to sum up the price there.

MySql SELECT get 1 record from multiple record

I have a table which looks something like :
id name qty price rev
1 book1 2 $10 0
2 book2 1 $5 0
3 book1 3 $15 1
4 book3 2 $10 0
5 book4 3 $15 0
6 book2 3 $15 1
7 book2 4 $20 2
and the data that will be displayed on the web is,
no name qty price rev
1 book1 3 $15 1
2 book2 4 $20 2
3 book3 2 $10 0
4 book4 3 $15 0
This is the query that I use
<?php
$sql = mysql_query("SELECT SUM(qty*price) FROM data_ph_user ORDER BY id");
while($res = mysql_fetch_array($sql)){
?>
<!-- display result -->
<?php
$resf1 = $res['SUM(qty*price)']; if($resf1 == 0){ echo '0'; }else{ echo $resf1; }
?>
<!-- end display -->
<?php } ?>
so, now how to get the data?
I've done various kinds of queries by using 'WHERE' but do not get results
I got your point.. so you just want to select the line where qty is maximum per book name.. right??
try the below query
select
name, qty, price, rev
from
MyTestingTable
where
qty = (select max(qty) from MyTestingTable i where i.Name = MyTestingTable.Name)
order by MyTestingTable.name
you can have a look on given SQL fiddle as well.. it will give you the desired result..
http://sqlfiddle.com/#!2/9162c4/8
The reason is that SUM is an aggregate function. Such functions normally return one row: in this case, you would sum over the entire table unless you group by something.
If I understand your question correctly, you wish to list the highest revision of all elements?
SELECT *, MAX(rev) FROM data_ph_user GROUP BY `name`
Then it's only a matter of typesetting it correctly.

MySQL/PHP storing multiple data points

I am relatively new to programming and databases.
I have a MySQL database with a "sales" table. This table lists all sales in a state (i.e. each record is a particular sale), with fields for sellername, and buyerzip. I would like to have another table "seller" that would include sellername, and also include fields to define the sellers market area by zip code - say 50+ zip codes define a market, and the seller could define multiple markets.
These market areas would be used for future queries: showing all sales in a particular market area.
Where do I start in terms of thinking how to store that "market area" data, and then use it for future queries?
Thanks
Table structure:
Sales table: ID, sellerID, buyerZipcode, amount
Seller table: ID, sellerName
Market table: ID, marketName
SellerMarketLink table: ID, sellerID, marketID
MarketZipCode table: ID, marketID, zipCode
Example data
Encoding the information in the first comment to your question
Market table
1, "Store A, first market"
2, "Store A, second market"
3, "Store B market"
MarketZipCode table
1, 1, 1
2, 1, 2
...
7, 1, 7
8, 1, 8
9, 2, 4
10, 2, 5
...
14, 2, 9
15, 2, 10
16, 3, 1
17, 3, 2
18, 3, 3
19, 3, 8
20, 3, 9
21, 3, 10
22, 3, 11
23, 3, 12
Query
Total sales in a market for each seller. Note that since one zip code can be part of several markets, the total of all values in "Total Sales" can be larger than the sum of all 'amount' values in the Sales table.
select Market.marketName, Seller.sellerName, sum(Sales.amount) as "Total Sales"
from Sales join Seller join SellerMarketLink join Market join MarketZipCode
on (Sales.sellerID = Seller.ID AND Seller.ID = SellerMarketLink.sellerID
AND SellerMarketLink.marketID = Market.ID
AND Market.ID = MarketZipCode.marketID
AND MarketZipCode.zipCode = Sales.buyerZipCode)
group by Market.ID, Market.marketName, Seller.ID, Seller.sellerName
order by Market.marketName, Seller.sellerName
I'm going to make the following assumptions here:
sellers have many markets
A market can span many zipcodes
Only one seller is responsible for a market
Markets can't overlap
Leading to the following structure...
sales table
seller | buyerzip
markets table
market | market_zipcodes_id
zipcodes table
market_id | zipcode
Hope that helps...

showing a grandtotal of values in a field

good pm. i was thinking is it possible to show the summation or grand total of a selected field in the table and with relation to date:
for example is i want to know the total beer consumption of my hotel every month.
i have here my table on services:
[services_id[pk],
customer_id[fk],
date_in,date_out,room_type,room_number,
extra_ref,
extra_bed,extra_snack,
extra_beer,extra_softdrinks,
extra_pillows,extra_breakfast,
extra_snack_q,
extra_beer_q,
extra_softdrinks_q,
extra_pillows_q,
extra_breakfast_q]
can you give some advice on how can i get it.
thanks in advance:
-renz
SELECT SUM(beer_amount) as monthly_beer_amount
FROM [DATABASE].[TABLE]
WHERE beer_sold_date BETWEEN '20110201' AND '20110228'
[EXTRA INFO]
Also I believe that the best way to organize this table is to separate out this table into a few other tables. Store customer info in the first table such as
[customer_id, customer_name, date_in, date_out, room_type, room_number].
1, Bob, 20110101, 20110110, big, 200
2, Joe, 20110101, 20110110, small, 202
....
And have another table named something like room_items which would have the following,
[id, item_name]
1, BEER
2, BED
3, SNACK
...
And then another table named room_purchases which will have the following,
[customer_id, purchase_id, amount, date....]
1, 1, 10, 20110101
2, 3, 5, 20110101
3, 1, 9, 20110101
....
This would help you to do a join on all three tables and they would be more normalized in this way.
SELECT SUM(t2.amount) as beer_amount
FROM customers as t1
LEFT JOIN room_purchases as t2 ON t1.customer_id = t2.customer_id
WHERE t2.purchase_id = 1 AND t2.date BETWEEN 20110101 AND 20110131
SELECT DATE_FORMAT(date_in,"%m-%Y") AS month,SUM(extra_beer) AS beers
FROM your_table
GROUP BY month
this will return something like this:
02-2011 | 43
03-2011 | 52
if you want to limit the query depending on the date just add a WHERE constraint before the GROUP BY

Categories