MYSQL NOT IN with multiple column names - mysql

i have 2 mysql queries,
1 is to select the all branch stocks and other is to select stock count lists.
i need to select all the branch stocks which is not included in stock count lists( by considering stock barcode and stock batch)
my first query to select all branch stock is
SELECT SQL_CALC_FOUND_ROWS stock_id ,product_name , stock_batch,stock_barcode
FROM stock INNER JOIN product ON product_id = stock_product
LEFT JOIN packing ON product_package=packing_id
WHERE stock_branch = 2 AND stock_available_flg = 1
group by stock_id
and second query to select counted stock lists is
SELECT SQL_CALC_FOUND_ROWS stock_id,stock_barcode, product_name,stock_batch FROM stock_count_item
INNER JOIN stock ON stock_id = stock_count_item_stock
INNER JOIN product ON stock_product = product_id
INNER JOIN category ON category_id = product_category
WHERE stock_count_item_stock_count = 42 GROUP BY stock_barcode
what i need is to select all branch stock which is not included in stock count lsts with same barcode and batch
my query is
SELECT SQL_CALC_FOUND_ROWS stock_id ,product_name , stock_batch,stock_barcode
FROM stock
INNER JOIN product ON product_id = stock_product
LEFT JOIN packing ON product_package=packing_id
WHERE stock_branch = 2 AND stock_available_flg = 1 AND ( stock_batch,stock_barcode)
not in
(SELECT stock_batch ,stock_barcode FROM stock_count_item
INNER JOIN stock ON stock_id = stock_count_item_stock
INNER JOIN product ON stock_product = product_id
INNER JOIN category ON category_id = product_category WHERE stock_count_item_stock_count = 42)
but this not gives the correct result .How am consider stock_batch,stock_barcode together to correct this?

Use NOT EXISTS instead of NOT IN
BUT because you have not identified which tables each column comes from so I (or anyone maintaining your code) cannot learn a column's source from reading the query. ALWAYS prefix the column by the table (or table's alias).
SELECT
SQL_CALC_FOUND_ROWS stock_id
, product_name
, stock_batch
, stock_barcode
FROM stock
INNER JOIN product ON product_id = stock_product
LEFT JOIN packing ON product_package = packing_id
WHERE stock_branch = 2
AND stock_available_flg = 1
NOT NOT EXSTS (
SELECT 1
FROM stock_count_item
INNER JOIN stock ON stock_id = stock_count_item_stock
INNER JOIN product ON stock_product = product_id
INNER JOIN category ON category_id = product_category
WHERE stock_count_item_stock_count = 42
and outer_alias.stock_batch = inner_alias.stock_batch
and outer_alias.stock_barcode = inner_alias.stock_barcode
)
;
I have tried to indicate what is required by using
and outer_alias.stock_batch = inner_alias.stock_batch
the "outer_alias" is an alias (or tablename) from before the NOT EXISTS subquery, and the inner_alias is the reverse. At least one of these has to be an alias if you choose to use a tablename for one of hem.
e.g.
select ... from stock where not exists (... from stock s and stock.id = s.id)
"stock" is the "outer_alias" of stock.id
"s" is the "inner_alias" of s.id
the final query with aliases (via comment below)
SELECT
SQL_CALC_FOUND_ROWS stock_id
, product_name
, s.stock_batch --<< please please please use aliases everywhere
, s.stock_barcode
FROM stock s
INNER JOIN product ON product_id = stock_product
LEFT JOIN packing ON product_package = packing_id
WHERE stock_branch = 2
AND stock_available_flg = 1
AND NOT EXISTS (
SELECT
1
FROM stock_count_item
INNER JOIN stock st ON stock_id = stock_count_item_stock
INNER JOIN product ON stock_product = product_id
INNER JOIN category ON category_id = product_category
WHERE stock_count_item_stock_count = 42
AND s.stock_batch = st.stock_batch
AND s.stock_barcode = st.stock_barcode
)

Related

Filtering query by passing idProduct, quantity

I want to create an Order_List with different ITEMS from a table called: Products
Inside table Products there are duplicates because a product is sell in different supermarkets, with differents prices.
I want the user to enter the desired product inside List table and get the lowest price. DO NOTE that every user has a different zipcode and every product belongs to a different supermarket with a different zipcode. The idea is to get the lowest price ONLY if the item has the same customer zipcode.Also, the quantity that was inserted in List table must be validated against Stock table.
This is what i have:
http://sqlfiddle.com/#!9/f9f73a/1
This is my example:
image
This is what i tried so far:
select p.idProduct, name, price, min(price)
from product p
inner join market m
on p.idMarket = m.idMarket
inner join stock s
on p.idProduct = s.idProduct
inner join list l
on p.idProduct = l.idProduct
where p.idProduct = 14
and exists (select 1
from stock s
where p.idProduct = s.idProduct
and l.quantity <= s.quantity)
group by p.idProduct, name, price
Could you please help me to solve this mess?
select p.idProduct, p.name, p.price, min(p.price)
from product p
inner join market m
on p.idMarket = m.idMarket
inner join stock s
on p.idProduct = s.idProduct
inner join list l
on p.idProduct = l.idProduct
where p.idProduct = 14
and exists (select 1
from stock s1
where p.idProduct = s1.idProduct
and l.quantity <= s1.quantity)
and p.price = (select min(price) from product p2 where p2.idProduct = p.idProduct)
group by p.idProduct, p.name, p.price

mysql #1242 - Subquery returns more than 1 row

This is for my thesis and the dead end is later i don't know what i do wrong here .. Im hoping that someone can help me to know what's wrong here thanks
SELECT
flower_id,
flower_name,
flower_description,
flower_price,
flower_category,
(quantity - (SELECT
SUM(q.quantity_value)
FROM
orders_details od
INNER JOIN
cart_details cd ON cd.cart_id = od.cart_id
INNER JOIN
quantities q ON q.quantity_id = cd.quantity_id
WHERE
od.flag = 1 AND cd.flower_id = flower_id
GROUP BY cd.flower_id)) AS 'quantity',
mfg_date,
exp_date
FROM
flower_details,
categories
WHERE
flower_details.flower_category = categories.category_id
What im doing here is getting the total quantity of products from customer bought minus to inventory stocks
If your subselect return more then a rows you should join the sum using an inner join on subselect
If your subselect return more then a rows you should join the sum using an inner join on subselect inner join on subselect
SELECT
flower_details.flower_id,
flower_name,
flower_description,
flower_price,
flower_category,
flower_details.quantity - t1.quantity,
mfg_date,
exp_date
FROM flower_details
INNER JOIN categories ON flower_details.flower_category = categories.category_id
INNER JOIN (
SELECT cd.flower_id ,
SUM(q.quantity_value) AS quantity
FROM
orders_details od
INNER JOIN
cart_details cd ON cd.cart_id = od.cart_id
INNER JOIN
quantities q ON q.quantity_id = cd.quantity_id
WHERE
od.flag = 1 AND cd.flower_id = flower_id
GROUP BY cd.flower_id
) t1 on flower_details.flower_id = t1.flower_id

Optimize query with multiple subquery joins

I have a query that gets the product description from product table (1st select) then subtracts it to the following subquery statements to get the no. of stocks remaining:
-sum of each product bought in the inventory table (2nd)
-sum of each product sold in the sales_detail table (3rd)
-sum of each product transferred to another branch in the stock_transfer table (4th)
-sum of each product that got damaged in the damaged_product table (5th)
The problem is every time this query loads, it goes full search of all 4 tables to get the sum of the quantity columns. And as time goes by, more records are stored and the query will become slower. Any suggestions?
SELECT p.Id,p.Product_Name Product,p.Description, c.Category_Name Category,sc.Subcategory_Name Subcategory,s.Supplier_Name Supplier, p.Selling_Price `Unit Price`,i.Stocks,s.Sales, i.Stocks - IFNULL(s.Sales, 0) - IFNULL(t.Transfer, 0) - IFNULL(d.Damage, 0) AS Remaining
FROM (SELECT Id, Product_Name, Description, Selling_Price, Category_Id, Subcategory_Id, Supplier_Id FROM product WHERE enable_flag = 1) p
LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(quantity), 0) AS Stocks
FROM inventory
WHERE enable_flag = 1 GROUP BY product_id) i ON p.Id = i.product_id
LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(quantity), 0) AS Sales
FROM sales_detail
WHERE enable_flag = 1 GROUP BY product_id) s USING(product_id)
LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(transfer_quantity), 0) AS Transfer
FROM stock_transfer
WHERE enable_flag = 1 GROUP BY product_id) t USING(product_id)
LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(damaged_quantity), 0) AS Damage
FROM damaged_product
WHERE enable_flag = 1 GROUP BY product_id) d USING(product_id)
JOIN Category c ON p.Category_Id=c.Id
JOIN Subcategory sc ON p.Subcategory_Id=sc.Id
JOIN Supplier s ON p.Supplier_Id=s.Id;
The use of subqueries prevents the use of indexes, which can slow down a query. I would suggest a query such as this:
SELECT p.*, sc.Subcategory_Name as Subcategory, s.Supplier_Name as Supplier,
p.Selling_Price as `Unit Price`,
(SELECT COALESCE(SUM(quantity), 0)
FROM inventory i
WHERE s.enable_flag = 1 AND s.product_id = p.product_id
) as stocks,
(SELECT COALESCE(SUM(quantity), 0)
FROM sales_detail sd
WHERE i.enable_flag = 1 AND i.product_id = p.product_id
) as sales,
(SELECT COALESCE(SUM(tansferquantity), 0)
FROM stock_transfer st
WHERE st.enable_flag = 1 AND st.product_id = p.product_id
) as transfers,
(SELECT COALESCE(SUM(damaged_quantity), 0)
FROM damage d
WHERE d.enable_flag = 1 AND d.product_id = p.product_id
) as damaged
FROM product p JOIN
Category c
ON p.Category_Id = c.Id JOIN
Subcategory sc
ON p.Subcategory_Id = sc.Id JOIN
Supplier s
ON p.Supplier_Id = s.Id
WHERE p.enable_flag = 1;
For performance, the underlying tables want indexes on (product_id, enable_flag, quantity). MySQL can use the index for aggregation in a correlated subquery.
I realize that you also have calculated values. You may need to do these calculations in an outer query, taking the hit of an additional materialization of the subquery.

Remove duplicate product with lower price using mysql query

I have many duplicate products that I need to delete. Is there a query to delete these "Duplicates" with the "lower price" and/or "Same Price" an just keep 1 of each product?
The duplicates have duplicate "Product Name" I am using Opencart Version 2.1.0.1
Since you are using mysql, you need to use joins (partition by is not supported):
The select:
select p.*
from products as p
join
(
select name, min(price) as price
from products group by name having count(price) = 2
) as p2 on p2.name = p.name and p2.price = p.price;
Gets the lowest price for all duplicate products (where duplicate assumes there are exactly two rows of the same product).
To delete, change the initial select to a delete, as follows:
delete p.*
from products as p
join
(
select name, min(price) as price
from products group by name having count(price) = 2
) as p2 on p2.name = p.name and p2.price = p.price;
According to the schema on http://wiki.opencarthelp.com/doku.php?id=databse_schema and only one language the folowing query should solve your issue:
delete p1
from product p1
join product_description d1 on d1.product_id = p1.product_id
join product_description d2
on d2.product_id <> d1.product_id
and d2.language_id = d1.language_id
and d2.name = d1.name
join product p2 on p2.product_id = d2.product_id
where d1.language_id = 1 -- define the language used for product name
and (p2.price > p1.price -- delete if higher price exists
or p2.price = p1.price and p2.product_id < p1.product_id -- delete if same price with lower id exists
)
;
Without much info (which RDBMS, etc) I can only speculate this solution would work for you:
WITH Flagged AS
(
SELECT
ProductName,
CASE WHEN ROW_NUMBER() OVER(PARTITION BY ProductName ORDER BY Price DESC) = 1 THEN 0 ELSE 1 END AS Delete
FROM
Products
)
DELETE p
FROM Products p
JOIN Flagged f
ON (p.ProductName = f.ProductName)
WHERE f.Delete = 1;

How to make a "distinct" join with MySQL

I have two MySQL tables (product and price history) that I would like to join:
Product table:
Id = int
Name = varchar
Manufacturer = varchar
UPC = varchar
Date_added = datetime
Price_h table:
Id = int
Product_id = int
Price = int
Date = datetime
I can perform a simple LEFT JOIN:
SELECT Product.UPC, Product.Name, Price_h.Price, Price_h.Date
FROM Product
LEFT JOIN Price_h
ON Product.Id = Price_h.Product_id;
But as expected if I have more than one entry for a product in the price history table, I get one result for each historical price.
How can a structure a join that will only return one instance of each produce with only the newest entry from the price history table joined to it?
Use:
SELECT p.upc,
p.name,
ph.price,
ph.date
FROM PRODUCT p
LEFT JOIN PRICE_H ph ON ph.product_id = p.id
JOIN (SELECT a.product_id,
MAX(a.date) AS max_date
FROM PRICE_H a
GROUP BY a.product_id) x ON x.product_id = ph.product_id
AND x.max_date = ph.date
SELECT Product.UPC, Product.Name, Price_h.Price, Price_h.Date
FROM Product
LEFT JOIN Price_h
ON (Product.Id = Price_h.Product_id AND Price_h.Date =
(SELECT MAX(Date) FROM Price_h ph1 WHERE ph1.Product_id = Product.Id));
Try this:
SELECT Product.UPC, Product.Name, Price_h.Price, MAX(Price_h.Date)
FROM Product
INNER JOIN Price_h
ON Product.Id = Price_h.Product_id
GROUP BY Product.UPC, Product.Name, Price_h.Price
SELECT n.product_id,
n.product_name,
n.product_articul,
n.product_price,
n.product_discount,
n.product_description,
n.product_care,
(SELECT photo_name FROM siamm_product_photos WHERE product_id = n.product_id LIMIT 1) AS photo_name
FROM siamm_product as n;
Why not keep it simple and fast:
SELECT
Product.UPC, Product.Name, Price_h.Price, Price_h.Date
FROM
Product
LEFT JOIN
Price_h
ON Product.Id = Price_h.Product_id;
ORDER BY
Price_h.Date DESC
LIMIT 1