Find customers that never placed an order with an employee - mysql

We have the following details from the output of a query a supplier id, a category name, and product count,
so 3 columns. Each supplier holds a certain category of products, and for each
category, the third column lists the number of products in that particular category.
How to write a query using this table which returns -
supplier if, category name, prodcount*100/totalnumberofproducts
Basically it should list the % of product in that category
The initial query that give the product count for each category is:
SELECT s.SupplierID, s.CompanyName AS Supplier, cat.CategoryName,
COUNT(*) AS CatProductCount
FROM suppliers AS s
JOIN products AS p ON s.SupplierID = p.SupplierID
JOIN categories AS cat ON p.CategoryID = cat.CategoryID
GROUP BY s.SupplierID, s.CompanyName, cat.CategoryName;
My Thoughts:
So if the initial query is S.
We could do
select supplierId, sum(productCount) as total from S groupby supplierID
This will tell us the total number of product for each supplier.
Let this query be called S2
select S.supplierId, (S.productCount*100)/S2.total from S inner join S2 on S.supplierID=S2.supplierId
I think I have the correct idea but the exact syntax I am using will not work.

you could use these two possibilities
As joined table
SELECT s.SupplierID, s.CompanyName AS Supplier, cat.CategoryName,
COUNT(*) * 100/ total as percentage_count
FROM suppliers AS s
JOIN products AS p ON s.SupplierID = p.SupplierID
JOIN categories AS cat ON p.CategoryID = cat.CategoryID
JOIN (select supplierId, sum(productCount) as total from suppliers group by supplierID ) S1 ON S1.supplierId = S,suppliers
GROUP BY s.SupplierID, s.CompanyName, cat.CategoryName;
Or as subselct
SELECT s.SupplierID, s.CompanyName AS Supplier, cat.CategoryName,
COUNT(*) * 100 / (select sum(productCount) from suppliers S1 WHERE S1.suppliers = S.supplierID ) as percentage_count
FROM suppliers AS s
JOIN products AS p ON s.SupplierID = p.SupplierID
JOIN categories AS cat ON p.CategoryID = cat.CategoryID
GROUP BY s.SupplierID, s.CompanyName, cat.CategoryName;
you should test both to see what is faster i would guess the second

Related

I'm getting an error when I try to use union

SELECT avg(Product.product_price)
From product
Where (
SELECT from customer
customer.city = "Tucson"
and Customer.cust_id = orders.cust_id
and Product.product_id = Orderline.product_id
)
group by product_name
UNION
SELECT sum(product.product_price)
From product
Where (
SELECT from customer
customer.city = "Tucson"
and Customer.cust_id = orders.cust_id
and Product.product_id = Orderline.product_id
)
group by product_name
I'm trying to display the average order from customers who order from tucson and the sum of the products going to tuscon
I have these tables with these (rows )orders (order_id, order_date, cust_id), product (product_id, product_name, product_price), orderLine (order_id, product_id, quantity), customer (cust_id, cust_name, street, city, state, zip) I need to 8. Show the average price and total price of products bought by customers from ‘Tucson’(Use Union) –
The problem is not with UNION - it's with the two queries you're attempting to UNION together. It looks to me like the AVG query should be something like:
SELECT avg(p.product_price)
From product p
INNER JOIN orderline ol
ON ol.product_id = p.product_id
INNER JOIN orders o
ON o.??????? = ol.???????
INNER JOIN customer c
ON c.cust_id = o.cust_id
WHERE c.city = 'Tuscon'
What's not clear from the code you posted is how the orders and orderline tables are to be joined - that is, what the common field(s) are in those tables. You'll need to fill that in.
Make similar changes to your SUM query.

SQL counting customers that have ordered the same product at least 7 times

I have the following tables
– Price (prodID, from, price)
– Product (prodID, name, quantity)
– PO (prodID, orderID, amount)
– Order (orderID, date, address, status, trackingNumber, custID, shipID)
– Shipping (shipID, company, time, price)
– Customer (custID, name)
– Address (addrID, custID, address)
I would like to find the names of customers who have bought the same item at least 7 times, if they bought the same item twice in one order I would like to count it as one. Here is my code:
SELECT C.name, COUNT(DISTINCT p.prodId) as prod_count
FROM Product P
INNER JOIN PO
ON PO.prodId = P.prodId
INNER JOIN "Order" O
ON O.orderId = PO.orderId
INNER JOIN Customer C
ON C.custId = O.custId
GROUP BY c.name
HAVING COUNT(DISTINCT p.prodId) > 6;
However, this is returning the number of unique products each customer has ordered which is not what I am looking for.
We can try using two levels of aggregation here. The first level of aggregation is by customer, order, and product, and removes duplicates should a given customer order the same product more than once within a single order. The next level of aggregation is only by customer and product, and it retains only customers who have at least one product which they purchased 7 or more times across different orders. Finally, we do a distinct select to retain each unique matching customer name.
WITH cte1 AS (
SELECT c.name, o.orderId, p.prodId
FROM Customer c
INNER JOIN "Order" o ON o.custId = c.custId
INNER JOIN PO po ON po.orderId = o.orderId
INNER JOIN Product p ON p.prodId = po.prodId
GROUP BY c.name, o.orderId, p.prodId
),
cte2 AS (
SELECT name, prodId
FROM cte1
GROUP BY name, prodId
HAVING COUNT(*) >= 7
)
SELECT DISTINCT name
FROM cte2;
As far as I see , there is no need of joining with Product table,unless you need Product name in your result.
;with CTE as(
SELECT orderId,prodId, COUNT(*) as OrderProd_Count
FROM dbo.PO
GROUP BY orderId,prodId
)
,CTE1 as(
SELECT prodId,count(*) as Prod_Count
from CTE
group by prodId
having count(*)>7
)
select c1.productid,ca.Name from CTE1 C1
inner join CTE C on c1.prodId=c1.prodId
inner join dbo.Order O on c.orderid=O.orderId
inner join Customer C on o.custid=C.custid

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: Ranking from multiple tables, sub queries?

This is a MySQL question. I have three tables with the following columns:
transactions (table): transact_id, customer_id, transact_amt, product_id,
products (table): product_id, product_cost, product_name, product_category
customers (table): customer_id, joined_at, last_login_at, state, name, email
I'd like a query that finds out the most popular item in every state and the state. One of the tricky parts is that some product_name have multiple product_id. Therefore I though joining the three tables that generate an output with two columns: state and product_name. Until here that worked fine doing this:
SELECT p.product_name, c.state
FROM products p
INNER JOIN transactions t
ON p.product_id = t.product_id
INNER JOIN customers c
ON c.customer_id = t.customer_id
This selects all the products, and the states from where the customer is. The problem is that I can't find the way to rank the mos popular product per state. I tried different group by, order by and using subqueries without success. I suspect I need to do subqueries, but I can't find the way to resolve it. The expected outcome should look like this:
most_popular_product | state
Bamboo | WA
Walnut | MO
Any help will be greatly appreciated.
Thank you!
You need a subquery that gets the count of transactions for each product in each state.
SELECT p.product_name, c.state, COUNT(*) AS count
FROM products p
INNER JOIN transactions t
ON p.product_id = t.product_id
INNER JOIN customers c
ON c.customer_id = t.customer_id
GROUP BY p.product_name, c.state
Then write another query that has this as a subquery, and gets the highest count for each state.
SELECT state, MAX(count) AS maxcount
FROM (
SELECT p.product_name, c.state, COUNT(*) AS count
FROM products p
INNER JOIN transactions t
ON p.product_id = t.product_id
INNER JOIN customers c
ON c.customer_id = t.customer_id
GROUP BY p.product_name, c.state
) AS t
GROUP BY state
Finally, join them together:
SELECT t1.product_name AS most_popular_product, t1.state
FROM (
SELECT p.product_name, c.state, COUNT(*) AS count
FROM products p
INNER JOIN transactions t
ON p.product_id = t.product_id
INNER JOIN customers c
ON c.customer_id = t.customer_id
GROUP BY p.product_name, c.state
) AS t1
JOIN (
SELECT state, MAX(count) AS maxcount
FROM (
SELECT p.product_name, c.state, COUNT(*) AS count
FROM products p
INNER JOIN transactions t
ON p.product_id = t.product_id
INNER JOIN customers c
ON c.customer_id = t.customer_id
GROUP BY p.product_name, c.state
) AS t
GROUP BY state
) AS t2 ON t1.state = t2.state AND t1.count = t2.maxcount
This is basically the same pattern as SQL select only rows with max value on a column, just using the first grouped query as the table you're trying to group.

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.