SQL average and Join - mysql

I'm trying to merge these two statements into one query to get the a list of product names(or ids) against the average of their TTFF data, and I'm stuck.
select AVG(TTFF) from TTFFdata group by product_id
select product.product_name, count(*) from product join TTFFdata on product.product_id = TTFFdata.product_id
I've looked into using a temporary table (CREATE TEMPORARY TABLE IF NOT EXISTS averages AS (select AVG(TTFF) from TTFFdata group by product_id)) but couldn't get that to work with a join.
Anyone able to help me please?

You need to understand the components. Your second query is missing a group by. This would seem to be what you want:
select p.product_name, count(t.product_id), avg(t.TTFF)
from product p left join
TTFFdata t
on p.product_id = t.product_id
group by p.product_name

It is better to do group by on product_id, product_name for two reasons. One is, you can select product id along with product name. Second reason is, If the product name is not unique then it may give wrong results(this may be a rare scenario like product name is same but it differs based on other columns like version or model). The below is the final query.
select Product.product_id,
product_name,
AVG(TTFF) as Avg_TTFF
from Product
inner join
TTFFdata
on Product.product_id = TTFFdata.product_id
group by Product.product_id,Product.product_name
TTFFdata:
product:
Output:

Related

sql nested query with group by

I was reading some tutorials about group by clause, i faced the following problem and don't know why it was solved like that, the table is as follows:
the requirement is to select the most expensive product in each category, and the following query was the answer:
SELECT
categoryID, productID, productName, MAX(unitprice)
FROM
products A
WHERE
unitprice = (
SELECT
MAX(unitprice)
FROM
products B
WHERE
B.categoryId = A.categoryID)
GROUP BY categoryID;
i don't know why the above query was the answer, why it wasn't just:
SELECT
categoryID, productID, productName, MAX(unitprice)
FROM
products
GROUP BY categoryID;
also, if the first query is the right one, why MAX function exists in the outer and inner query, isn't it enough to exist in the inner query?
thanks.
The second query will produce an error because it is not possible to have columns in the select clause whitout grouping by them in the Group by clause (unless they are subject to the aggregation).
Therefore you need to first find the highest unit price in each category and then find which product has that uniprice. You can actually accomplish this in many ways. This first query is one of them.
From your picture it looks as others have mentioned that you are using mysql, the MYSQL optimiser doesn't like subqueries very much and it would horrible to run over lots of data, best habit is to use joins where possible (if you look at query plans in postgres, oracle or mssql it will re-write sub-queries as joins 90% of the time)
The second query will run on default mysql as it will group by the missed columns you missed.
Below is an example:
SELECT
A.categoryID, A.productID, A.productName, B.max_unitprice
FROM products A
JOIN (
SELECT
max(unit price) as max_unitprice,
categoryId
FROM products
GROUP BY categoryId) B
ON B.categoryId = A.categoryID
SELECT p.*
FROM products p
WHERE NOT EXISTS ( SELECT 'p2'
FROM products p2
WHERE p2.categoryId = p.categoryId
AND p2.unitPrice > p.unitPrice
)

SQL Join, right ? left ? inner?

working with mySql I would like to list all purchases that customers made on a specific cathegory of products.
So, I had 3 tables: customers (idCustomer, Name) , cathegories (idCategory, CategoryName) and orders (idOrder, idCustomer, idCathegory, Qty, Price)
But I want a listing with ALL of the customers.
Not only the one who bought that specific idCategory
I thought something like:
select sum(Orders.Qty), Customers.Name
from Orders
right join Customers on Orders.idCustomer = Customer.idCustomer
where Orders.idCategory = 'Notebooks'
group by Orders.idCategory
but this statement only lists the records for customers who exists in Orders table.
And I want all of them ( the one who didnt buy, with qty =0 )
thanks in advance
Most people find left join easier to follow than right join. The logic for left join is to keep all rows in the first table, plus additional information from the remaining tables. So, if you want all customers, then that should be the first table.
You will then have a condition on the second table. Conditions on all but the first table should be in the on clause rather than a where. The reason is simple: when there is no match, then the value will be NULL and the where condition will fail.
So, try something like this:
select sum(o.Qty) as sumqty, c.Name
from Customers c left join
Orders o
on o.idCustomer = c.idCustomer and
o.idCategory = 'Notebooks'
group by c.Name;
Finally, the group by should have a relationship to the select clause.
Try this query
select sum(Orders.Qty), Customers.Name
from Customers
right join Orders on Customer.idCustomer = Orders.idCustomer and Orders.idCategory = 'Notebooks'
group by Customers.Name

Get all the products, and putting a specific order's product first

I have 3 tables: products, orders and orderLines(order_id, product_id).
I have an sql query to figure out which seems nearly impossible to do in only one query.
Is there a way to have in only one query:
All the products but showning a specific order's products first;
which means that: for an order A: show product1, product2.. present in orderA's orderLines first, than the following products (not ordered) are shown next.
PS:
I know it's possible to achieve this with a union of two queries, but it would be better to have it done in only one query.
You can put a subquery in the order by clause. In this case, an exists subquery is what you need:
select p.*
from products p
order by (exists (select 1
from orderlines ol
where p.productid = ol.productid and o.orderid = ORDERA
)
) desc;

Joining two tables and selecting from the result

I am trying out SQL and having trouble figuring out making queries when it comes to combining info from multi tables. Been using w3school but they don't seem to have similar reference to the question below. Was thinking of joining them as my codes below but still that doesn't answer the question. Appreciate any advice. Thanks.
Question:
Products(itemID, description, quantity, supplierID)
Supplier(supplierID, name, address)
A product can be supplied by more than one supplier. Write the SQL to
list the quantity of each product by each supplier.
SELECT Products.quanity, Supplier.name
FROM Products INNER JOIN Supplier
ON Products.supplierID = Supplier.supplierID;
Assuming that the product table does not have two rows for the same supplier and product, then your query is very close. I would write it as:
SELECT p.description as ProductDescription, s.name as SupllierName, p.Quantity
FROM Products p INNER JOIN
Supplier s
ON p.supplierID = s.supplierID
ORDER BY p.description, p.Quantity desc;
Note the following:
The use of tables aliases (the p and s) make the query more readable and are used for every column reference.
The final result is explicitly order by product, with the largest quantity first.
If there are multiple rows for a given product and supplier, then you will need aggregation.
Looks like you need to use group by here:
select itemId, supplierId, sum(quantity) from Products group by itemId, supplierId;

Get minimum price with left join / result reduced

I am coding an online shop. A product has a default price, but since it might have different attributes (color, size, ...), those different attributes might result in different prices as well. At the moment I am trying to produce a mysql query which helps me to find the minimum and maximum possible price of a product. Using LEFT JOIN currently reduces the query's result to only one row and I don't know why.
SELECT
products.id AS id,
categories.name AS category_name,
MIN(product_attributes.price) AS min_price, MAX(product_attributes.price) AS max_price,
products.*
FROM products
LEFT JOIN categories ON category_id=categories.id
LEFT JOIN product_attributes ON products.id=product_attributes.product_id
Is this even the correct approach? I do not know that much about mysql, I just try and try and I am happy if it works. Thanks for help anyway.
You are missing a GROUP BY clause in your current query, but I would recommend using a subquery to get the result:
SELECT
p.id AS id,
c.name AS category_name,
pa.min_price,
pa.max_price,
p.*
FROM products p
LEFT JOIN categories c
ON p.category_id = c.id
LEFT JOIN
(
select MIN(product_attributes.price) min_price,
MAX(product_attributes.price) max_price,
product_id
from product_attributes
group by product_id
) pa
ON p.id=pa.product_id
The main reason why I would suggest using a subquery is because MySQL MySQL uses a EXTENSION TO GROUP BY which allows the behavior of not enforcing the FULL GROUP BY.
This extension in MySQL can cause unexpected values to be returned in the columns in the SELECT list that are not in the GROUP BY clause or in an aggregate function.
From the MySQL Docs:
MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. ... You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Sorting of the result set occurs after values have been chosen, and ORDER BY does not affect which values the server chooses.
you need to have GROUP BY clause,
SELECT
products.id AS id,
categories.name AS category_name,
MIN(product_attributes.price) AS min_price,
MAX(product_attributes.price) AS max_price.
products.*
FROM products
LEFT JOIN categories ON category_id=categories.id
LEFT JOIN product_attributes ON products.id=product_attributes.product_id
GROUP BY products.id, categories.name
but be careful when using GROUP BY in mysql, as the statement is perfectly valid if ONLY_FULL_GROUP_BY is disabled by default.
The correct way of doing the query is by using a subquery which separately gets minimum price for each product.
SELECT a.id AS id,
b.name AS category_name,
c.minPrice,
c.maxPrice,
a.*
FROM products a
LEFT JOIN categories b
ON a.category_id = b.id
LEFT JOIN product_attributes c
(
SELECT product_id,
MIN(product_attributes.price) minPrice,
MAX(product_attributes.price) maxPrice
FROM product_attributes
GROUP BY product_id
) d ON a.id = c.product_id