Need help on query sum total quantity show wrong output - mysql

Process:
When user buy item and check out then there's cart and cart items table to store the transaction.
1 cart_id have many item which stored in cart items table.
After purchase succeed, then will generate a purchase order id and stored in purchase order table .
In purchase order table, id_cart and status will be stored.
From here, i am trying to calculate quantity based on id_product or id branch or etc from the purchase made.
There is receiving and ordered quantity field, which in some cases quantity received field might be null, so i will take ordered quantity value.
This is my query
SELECT id_product,sum(DISTINCT(COALESCE(received_qty, quantity)))
FROM (SELECT C.id_cart,C.received_qty,C.quantity , P.id_product,
PO.id_purchase_order, PO.status
FROM (SELECT * FROM cart_items WHERE id_cart IN (SELECT id_cart FROM purchase_orders)) AS C
LEFT JOIN products as P on p.id_product = c.id_product
LEFT JOIN purchase_orders AS PO ON C.id_cart = PO.id_cart ) AS A
GROUP By A.id_product
Table data
The cart id in will be duplicated based on product's supplier. Because need to track and send separately to supplier.
Result
By right the product id for 1212 should be 1 and 1223 is 2, total qty =3.
What's wrong with my query ?

Your outer joins seem to cause multiplication of your data, but there are so many unnecessary layers of fluff in your query that I cant make it out exactly.
How about just this:
SELECT id_product, sum(COALESCE(received_qty, quantity)) AS Nmbr
FROM cart_items
GROUP BY id_product
If you want to make sure the cart is in your purchase_orders:
SELECT c.id_product, sum(COALESCE(c.received_qty, c.quantity)) AS Nmbr
FROM cart_items c
JOIN (SELECT DISTINCT id_cart FROM purchase_orders) p ON p.id_cart = c.id_cart
GROUP BY c.id_product

Related

Find items not listed using three table master sku table,sold,not sold

We ave three tables
Mastersku Table which has all the SKU's
Sold Table: has all the SKU's which had at least 1 qty sale along with the portal name in which it has been sold
Not sold Table: has SKU's which are listed on the portal but not sold along with the portal name
Need SKU's list from Mastersku with a column which says sold, notsold, notlisted. an SKU which is not present in both sold and not sold tables would be considered as not listed my code is below guess need to join it with Mastersku where the field name is SKU and in the other two tables it is Trim Sku. Have added distinct as Trim Sku is duplicate in sold and not sold table.just in case SKU present in sold and notsold for a given portal means it is the wrong sold should precede. we at present move SKU's from not sold to sold manually.
select DISTINCT `portal`,`Trim Sku`,'sold' TableName from sold
UNION ALL
select DISTINCT `portal`,`Trim Sku`,'notsold' TableName from notsold
I'd left join the mastersku table on the other two, and use a case expression to understand if it's sold or not:
SELECT m.*,
CASE WHEN s.`trim sku` IS NOT NULL THEN 'sold'
WHEN n.`trim sku` IS NOT NULL THNE 'not sold'
ELSE 'not listed'
END AS status
FROM mastersku m
LEFT JOIN sold s ON m.`sku` = s.`trim sku`
LEFT JOIN notsold n ON m.`sku` = n.`trim sku`

MySQL Query - Get Customers who have not bought all parts of a single product ID

Okay so I have 2 tables. One table for Product List and one table for Orders. There will be several of the same ProductID in my Table1 since each ProductID has several parts to it (IE: Part 1 of 7.)
The PartNumber will be a number. How do I design my query to find me all the customers who have purchased one of the part numbers, but not all the part numbers for a single product ID?
I'm just learning the basics of MySQL so any help would be much appreciated!
Table1 - Product List
UniqueIDKey
Product ID
PartNumber
Table2 - Orders
UniqueIDKey
Product ID Ordered
PartNumber Ordered
Customer ID
So an order might look like this:
UniqueIDKey: 77
Product ID Ordered: 1001
PartNumber Ordered: 3
Customer ID: 2000001
And, several rows of my Table1 - Product List might look like this:
UniqueIDKey Product ID PartNumber
77 1001 1
78 1001 2
79 1001 3
You need to know the total number of parts under each product prior
to knowing which customers bought some parts of a product but not the
whole.
The query enclosed by table alias B provides count of parts for
each product.
The query enclosed by table alias A provides for each
<customer,product> pair the total number of bought parts.
Now the rest is to match whether the total number of bought parts is
less than the total number of parts of a product.
In this approach the query would look like below:
SELECT
A.customer_id,
A.product_id,
A.total_parts_of_product_customer_purchased AS total_purchased,
B.total_parts,
B.total_parts - A.total_parts_of_product_customer_purchased AS didnot_purchase
FROM (
SELECT
customer_id,
product_id,
count(part_number) AS total_parts_of_product_customer_purchased
FROM Orders AS ordr
GROUP BY
customer_id, product_id
) AS A
INNER JOIN (
SELECT
product_id,
count(part_number) AS total_parts
FROM product_list AS pl
GROUP BY product_id
) AS B
ON A.product_id = B.product_id
WHERE A.total_parts_of_product_customer_purchased < B.total_parts
ORDER BY A.customer_id;
Use a cross join to get all combinations of customers,product_id's and part_numbers. left join orders table on to this result to get customers who haven't ordered all the parts in a product.
select c.customer_id,p.product_id
from (select product_id,part_number from product_list) p
cross join (select distinct customer_id from orders) c
left join orders o on p.product_id=o.product_id and p.part_number=o.part_number and c.customer_id=o.customer_id
group by c.customer_id,p.product_id
having count(o.part_number) < count(p.part_number)

Inverse of Inner join (Intersect) with multiple foreign keys

Hi I want to get opposite of intersect from two tables.
I have a sale table and purchase table. What I want to do is get all purchases ids where not included in the sales table.
sale table
sale_id (pk)
product_id (fk)
purchase_id (fk)
purchase table
product_id (fk)
purchase_id (pk)
SELECT DISTINCT purchase_id
, product_id
FROM
purchase
INNER JOIN sale
USING (purchase_id, product_id);
Here is an example:
If I run the above code, this will be the result.
purchase_id product id
1 1
1 2
1 4
2 1
2 3
Now I want to get:
purchase_id product id
1 3
2 2
In short I want to get inverse of above code. Thanks in advance.
Okay, I think I understand better now.
This should return any entry in purchase that have no matching entry in sales.
SELECT
`purchase`.`purchase_id`, `purchase`.`product_id`
FROM `purchase`
LEFT JOIN `sale` ON `sale`.`purchase_id` = `purchase`.`purchase_id` AND `sale`.`product_id` = `purchase`.`product_id`
WHERE
`sale`.`sale_id` IS NULL
ORDER BY
`purchase`.`purchase_id`, `purchase`.`product_id`
If you want to get all the purchases that have no related values in the sales table, you can use a LEFT JOIN:
select
p.purchase_id
from
purchase as p
left join sale as s on p.purchase_id = s.purchase_id
where
s.purchase_id is null;
"Unilateral" joins (LEFT JOIN, RIGHT JOIN) are useful when you want to get data from a table even if data in another related table does not exist. Of course, that means that you can filter data from one table when there's no related data in a second table.
Hope this helps.
Looking at your updated question and your comment, I think that you want all the possible combinations not used.
You'll need to split this in two steps:
First you need all the possible combinations of purchase_id and sale_id values (the "cartesian product" of both the sets).
Then you need to get all the combinations already used.
Finally you need to exclude all the combinations already used.
This can be done using subqueries.
Step 1.
select distinct p.purchase_id, s.product_id from purchase as p, sale as s;
Step 2. (Your query)
select distinct
purchase_id, product_id
from
purchase as p
inner join sale as s
on (p.purchase_id = s.purchase_id and p.product_id = s.product_id);
Step 3. Put it all together
select
a.*
from
(select distinct p.purchase_id, s.product_id from purchase as p, sale as s) as a
left join (
select distinct
purchase_id, product_id
from
purchase as p
inner join sale as s
on (p.purchase_id = s.purchase_id and p.product_id = s.product_id)
) as e on (a.purchase_id = e.purchase_id and a.product_id = e.product_id)
where
e.purchase_id is null and e.product_id is null;

List all products with no prices in MySQL

This query is for a niche price comparison website.
I have 2 tables, the first lists product details and the second lists all the prices associated with the product. A product can have one or many prices.
I am looking to list all the products that have no active prices for housekeeping purposes.
It is possible to have an entry in the price table where the price = zero, in which case Prod_price_active would be set to "0". If a product does have a price, then Prod_price_active would be set to "1"
Table 1
Prod_id
Prod_name
Prod_description
Table 2
Price_id
Prod_id
Prod_price
Prod_price_active
The simplest query to understand is:
select * from table1
where not exists (
select * from table2
where Prod_price_active = 1
and Prod_id = table1.Prod_id)
This is the SQL version of the sentence "give me all products that don't have an active price"
Assuming every product is in the price table, you can do an inner join.
select a.Prod_id, a.Prod_name, a.Prod_description
from PRODUCTS a inner join PRICES b
on a.Prod_id = b.Prod_id
where b.Prod_price_active=0
You are looking for a way to perform an anti-join:
SELECT table1.* FROM table1
LEFT JOIN table2 USING(prod_id)
WHERE Prod_price IS NULL
OR Prod_price_active = 0
This will keep only those rows from table1 (the "product table") that don't have a corresponding entry on table2 (the "price table") or those having Prod_price_active set to 0.

MySQL Recommend an item.

I am trying to run a query that for a selected person, it will recommend items based on their purchase history and what other people have bought who also bought that item.
Example:
Customer 1 purchases item A, and B.
Customer 2 purchases item B.
Customer 2 is recommended, item A.
I have 4 tables that are used in this I will list them with the relevant row names.
Customer
PK: Cust_ID
Session
PK: Ses_ID
FK: Cust_ID
Order
PK: Order_ID
FK: ItemRef_ID
FK: Session_ID
Item
PK: Item_ID
I'm pretty new to SQL but here's what I've got so far, following that I really have no idea how to go about doing it.
Currently it only gives the items that the selected customer has bought 'Lani Morgan', but instead I'd like it to display items that other customers have bought, who have bought the item 'Lani Morgan' has bought.
SELECT Item_Desc, Item_ID
FROM rbickers.Item
LEFT JOIN rbickers.Order
ON Item.Item_id = Order.itemref_id
LEFT join rbickers.Session
ON Order.Session_id = Session.Ses_id
left join rbickers.customer
On customer.cust_ID = session.Cust_ID
Where Cust_First = "Lani" and Cust_Last = "Morgan"
GROUP BY Item_Type
LIMIT 10
Any help would really be appreciated, thanks.
So by your basic version and with the supplied schema, the way I see it implemented is by checking for every item, if not bought by customer1, but bought by any other customer buying items customer1 has bought.
Since this schema requires you to join through all of the given tables, I'd ask you to create a view of the join you've provided:
create view CustomerItems as
SELECT *
FROM rbickers.Item
LEFT JOIN rbickers.Order
ON Item.Item_id = Order.itemref_id
LEFT join rbickers.Session
ON Order.Session_id = Session.Ses_id
left join rbickers.customer
On customer.cust_ID = session.Cust_ID
#Where Cust_First = "Lani" and Cust_Last = "Morgan"
and then:
select distinct item.* from item, CustomerItems cust1 where
cust1.Cust_First="Lani" and cust1.Cust_Last="Morgan" and
item.Item_ID not in(
select Item_ID from CustomerItems cust2 where cust1.Cust_ID=cust2.Cust_ID)
and exists(select * from CustomerItems cust3 where
cust3.Cust_ID<>cust1.cust_ID and item.Item_ID=cust3.Item_ID);