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

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.

Related

Find customers that never placed an order with an employee

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

SQL query how to compare string

There are two tables:
Customers:
ID
Name
Surname
City
Orders:
OrderId
CustomerId
Purchase
Price
I'm trying to find customer id,name,surname where he hasn't Purchase "Pizza".
Any help to fix my query? I tried with cp.Purchase != "Pizza" but doesn't work
SELECT DISTINCT ID,FirstName,LastName
FROM Customers c
INNER JOIN Orders cp ON c.ID = cp.OrderID
ORDER BY c.ID
WHERE cp.Purchase LIKE '%Pizza%'
try this
select * from Customers where Id not in (
select CustomerId From Orders WHERE cp.Purchase LIKE '%Pizza%'
)
The right query is
SELECT DISTINCT c.ID, c.Name, c.Surname
FROM Customers c JOIN Orders o on c.ID = o.CustomerID
WHERE c.ID <> ALL (
SELECT c2.ID
FROM Customers c2 JOIN Orders o2 on c.ID = o2.CustomerID
WHERE o2.Purchase = 'Pizza')
This is because you are looking for who never bought a pizza, so you will select data of customers which ID never appear (<> ALL) in orders table in a record where a pizza was bought.
By the way, check also SQL base, try understand before getting the answer.

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

Using SUM with Joins in MySQL returns unexpected result

I have these tables : customers, customer_invoices, customer_invoice_details, each customer has many invoices, and each invoice has many details.
The customer with the ID 574413 has these invoices :
select customer_invoices.customer_id,
customer_invoices.id,
customer_invoices.total_price
from customer_invoices
where customer_invoices.customer_id = 574413;
result :
customer_id invoice_id total_price
574413 662146 700.00
574413 662147 250.00
each invoice here has two details (or invoice lines) :
first invoice 662146:
select customer_invoice_details.id as detail_id,
customer_invoice_details.customer_invoice_id as invoice_id,
customer_invoice_details.total_price as detail_total_price
from customer_invoice_details
where customer_invoice_details.customer_invoice_id = 662146;
result :
detail_id invoice_id detail_total_price
722291 662146 500.00
722292 662146 200.00
second invoice 662147 :
select customer_invoice_details.id as detail_id,
customer_invoice_details.customer_invoice_id as invoice_id,
customer_invoice_details.total_price as detail_total_price
from customer_invoice_details
where customer_invoice_details.customer_invoice_id = 662147;
result :
detail_id invoice_id detail_total_price
722293 662147 100.00
722294 662147 150.00
I have a problem with this query :
select customers.id as customerID,
customers.last_name,
customers.first_name,
SUM(customer_invoices.total_price) as invoice_total,
SUM(customer_invoice_details.total_price) as details_total
from customers
join customer_invoices
on customer_invoices.customer_id = customers.id
join customer_invoice_details
on customer_invoice_details.customer_invoice_id = customer_invoices.id
where customer_id = 574413;
unexpected result :
customerID last_name first_name invoice_total details_total
574413 terry amine 1900.00 950.00
I need to have the SUM of the total_price of the invoices, and the SUM of the total_price of the details for each customer. In this case I'm supposed to get 950 as total_price for both columns (invoice_total& details_total) but it's not the case. what am I doing wrong & how can I get the correct result please. The answers in similar topics don't have the solution for this case.
When you mix normal columns with aggregate functions (for example SUM), you need to use GROUP BY where you list the normal columns from the SELECT.
The reason for the excessive amount in total_price for invoices is that the SUM is also calculated over each detail row as it is part of the join. Use this:
select c.id as customerID,
c.last_name,
c.first_name,
SUM(ci.total_price) as invoice_total,
SUM((select SUM(d.total_price)
from customer_invoice_details d
where d.customer_invoice_id = ci.id)) as 'detail_total_price'
from customers c
join customer_invoices ci on ci.customer_id = c.id
where c.id = 574413
group by c.id, c.last_name, c.first_name
db-fiddle
I used join against sub queries and then did a sum on the sums
SELECT c.id as customerID,
c.last_name,
c.first_name
SUM(i.sum) as invoice_total,
SUM(d.sum) AS details_total
FROM customers c
JOIN (SELECT id, customer_id, SUM(total_price) AS sum
FROM customer_invoices
GROUP BY id, customer_id) AS i ON i.customer_id = c.id
JOIN (SELECT customer_invoice_id as id, SUM(total_price) AS sum
FROM customer_invoice_details
GROUP BY customer_invoice_id) AS d ON d.id = i.id
WHERE c.id = 574413
GROUP BY c.id, c.name
The issue is in the joining logic. The table customers is used as the driving table in the joins. But in the second join, you are using a derivative key column from the first join, to join with the third tables. This is resulting in a Cartesian output doubling the records from the result from the nth-1 join, which is leading to customer_invoices.total_price getting repeated twice, hence the rolled up value of this field is doubled.
At a high level I feel that the purpose of rolling up the prices is already achieved in SUM(customer_invoice_details.total_price).
But if you have a specific project requirement that SUM(customer_invoices.total_price) should also be obtained and must match with SUM(customer_invoice_details.total_price), then you can do this:
In a separate query, Join customer_invoice_details and customer_invoices. Roll up the pricing fields, and have a result such that you have only one record for one customer ID.
Then use this as a sub-query and join it with the customers table.
You are aggregating along multiple dimensions. This is challenging. I would suggest doing the aggregation along each dimension independently:
select c.id as customerID, c.last_name, c.first_name,
ci.invoice_total,
cid.details_total
from customers c join
(select ci.sum(ci.total_price) as invoice_total
from customer_invoices ci
group by ci.customer_id
) ci
on ci.customer_id = c.id join
(select ci.sum(cid.total_price) as details_total
from customer_invoices ci join
customer_invoice_details cid
on cid.customer_invoice_id = ci.id
group by ci.customer_id
) cid
on cid.customer_id = c.id
where c.id = 574413;
A faster version (for one customer) uses correlated subqueries:
select c.id as customerID, c.last_name, c.first_name,
(select ci.customer_id, sum(ci.total_price) as invoice_total
from customer_invoices ci
where ci.customer_id = c.id
) as invoice_total,
(select ci.customer_id, sum(cid.total_price) as details_total
from customer_invoices ci join
customer_invoice_details cid
on cid.customer_invoice_id = ci.id
where ci.customer_id = c.id
) as details_total
from customers c
where c.id = 574413;

Error 1064 - In statement

I am trying to show the average price of products bought by customers from ‘Tucson’, however this query returns null even though there are two customers that have placed orders from Tuscon.
select AVG(product_price) from product where product_id in
(select product_id from orderline where order_id in
(select order_id from ordertable where cust_id in
(Select cust_id from customer where city = 'Tuscon')))
You're using fom instead of from in your query: select order_id fom ordertable where cust_id in
This should be select order_id from ordertable where cust_id in
fom is not a recognized keyword. The MySQL parser doesn't know what to do with that, so it throws an error about "invalid syntax".
Consider using join operations in place of nested IN subqueries. If we are guaranteed:
product_id is unique in product table
order_id is unique in ordertable table
cust_id is unique in customer table
then we can get an equivalent result set, the average of the price of distinct products that were ordered...
SELECT AVG(p.product_price)
FROM ( SELECT l.product_id
FROM orderline l
JOIN ordertable o
ON o.order_id = l.order_id
JOIN customer c
ON c.cust_id = o.cust_id
WHERE c.city = 'Tuscon'
GROUP BY l.product_id
) q
JOIN product p
ON p.product_id = l.product_id
If we want that "average price" of all products ordered (a different result, with the average taking into account the number of times a product was ordered...then we could use a query like this:
SELECT AVG(p.product_price)
FROM product p
JOIN orderline l
ON l.product_id = p.product_id
JOIN ordertable o
ON o.order_id = l.order_id
JOIN customer c
ON c.cust_id = o.cust_id
WHERE c.city = 'Tuscon'