I am trying to display the productid for the product that has been sold the most (i.e, that has been sold in the highest quantity)
I have tried multiple different versions of code but every time it says cannot nest aggregated operations
SELECT productid
FROM soldvia
GROUP BY productid
WHERE productid IN (SELECT MAX(SUM(noofitems)) FROM soldvia GROUP BY productid);
I expect the output to be
PRODUCTID
3x3
4x4
You can't nest aggregations.
Use ORDER BY with TOP :
SELECT TOP 1 productid
FROM soldvia
GROUP BY productid
ORDER BY SUM(noofitems) DESC
Please try below query for your exact answer.
select productid, sum(noofitems) as max_sold,
convert(varchar,productid) +' x '+ convert(varchar,sum(noofitems)) as
output_sold from soldvia group by productid order by sum(noofitems) desc
Output will be
ProductId NoOfItemSold Output_Sold
1 7 1x7
2 4 2x4
3 1 3x1
In Teradata, you can use the qualify clause:
SELECT productid
FROM soldvia
GROUP BY productid
QUALIFY ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC) = 1;
This is handy. You can get duplicates by changing ROW_NUMBER() to RANK(). Actually, RANK() is more consistent with the code in your question.
The answer by #forpas is probably the way to go but this one is a little closer to yours:
SELECT productid
FROM soldvia
GROUP BY productid
HAVING SUM(noofitems) = (
SELECT MAX(items)
FROM (
SELECT SUM(noofitems) AS items
FROM soldvia
GROUP BY productid
) x
)
Related
I would like to receive top 5 selling products in quantity in an order from NorthWind database.
The database has a bunch of tables like Order, OrderDetails, Customers, etc. I was suggested to use Orders Details table below:
Now, I tried the following:
WITH cte AS (
SELECT
OrderID,
Quantity,
ProductID,
ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY OrderID) as row_num
FROM [Order Details]
)
SELECT *
FROM cte
WHERE row_num IN (SELECT row_num FROM cte WHERE row_num <=10)
ORDER BY OrderID;
Thought this retrieves 10 rows now for each order, they are not ordered based on sold quantities and top sold products are not retrieved properly as for some orders the top sold was beyond the first top 10 rows based on row number I got with ROW_NUMBER() function in SQL.
Edit: For example, if I have 10 orders each with 20 products, then I want top 5 each each product, so the result table should have 50 rows total.
After your edits:
WITH cte AS (
SELECT
OrderID,
Quantity,
ProductID,
ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY Quantity DESC) as row_num
FROM [Order Details]
)
SELECT *
FROM cte
WHERE row_num <= 5
ORDER BY OrderID;
You should do a
SELECT DISTINCT productid FROM OrderDetails ORDER BY quantity GROUP BY productId LIMIT 5
At least this is the mysql syntax.
I have a problem with getting the top selling product from my database. This is the code I have tried:
SELECT productid
FROM soldvia
GROUP BY productid
HAVING SUM(noofitems) = (SELECT MAX(SUM(noofitems))
FROM soldvia
GROUP BY productid);
I get this error:
Msg 130, Level 15, State 1, Line 68
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
I have no idea what I am doing wrong, please help.
In SQL Server, you can write this as:
SELECT productid
FROM soldvia
GROUP BY productid
HAVING SUM(noofitems) = (SELECT TOP (1) SUM(noofitems)
FROM soldvia
GROUP BY productid
ORDER BY SUM(noofitems) DESC
);
The more typical way to write the query, though, uses RANK() or window functions:
SELECT productid
FROM (SELECT productid, SUM(noofitems) as numitems,
RANK() OVER (ORDER BY SUM(noofitems) DESC) as seqnum
FROM soldvia
GROUP BY productid
) t
WHERE seqnum = 1;
I have 2 tables:
Product(ProductID, ProductName, ProductPrice, VendorID, CategoryID)
SoldVia(ProductID, TID, NoOfItems)
I need to display the productID for the product that has been sold in the highest quantity. I can easily come up with the list sorted in ascending order with this query:
SELECT distinct productid, sum(noofitems)
From soldvia
Group By productid
Order By sum(noofitems) DESC
By question is, how do I only show the top value of the list, using the MAX function? I can't use LIMIT or TOP for this assignment, but whenever I use MAX, I run into various issues with aggregates.
After I'm done with that, how do I show the product name for the best selling product?
Thank you!
Give this a try:
SELECT prd.ProductId
FROM Product prd
INNER JOIN SoldVia sld ON prd.ProductId = sld.ProductId
WHERE prd.NoOfItems = (SELECT MAX(NoOfItems) FROM SoldVia) -- Check for item that has max # items sold
This will return the items with the highest aggregate value of NoOfItems
Update
I didn't know you were on Teradata. That makes life much much easier :)
SELECT ProductName
FROM Product prd
INNER JOIN (
SELECT ProductId, SUM(NoOfItems) AS TotalItemsSold
FROM SoldVia
GROUP BY ProductId
QUALIFY RANK() OVER(ORDER BY TotalItemsSold DESC) = 1 -- Only return ProductId(s) with largest TotalItemsSold value (includes ties)
) agg ON prd.ProductId = agg.ProductId -- Get aggregate # items sold (if any)
This will only return rows if there are matching rows in both tables.
This is a little more simple, but I think this still should work for you
select productid, max(itemsum)
from
(SELECT productid, sum(noofitems) as itemsum
FROM soldvia
group by productid)
;
Based on #ravioli's answer, without a subselect.
From logic I would prefer the subselect (early reducing the number of rows), but the explain shows, that 1 more step is used with the subselect. I expect it to be different for larger number of rows.
select
S.ProductID
, P.ProductName
, sum(NoOfItems) as TotalItemsSold
from SoldVia as S
inner join Product as P
on S.ProductID = P.ProductID
group by S.ProductID, P.ProductName
QUALIFY RANK() OVER(ORDER BY TotalItemsSold DESC) = 1 -- Only return ProductId(s) with largest TotalItemsSold
;
I am sorry if this seems too easy but I was asked this question and I couldn't answer even after preparing SQL thoroughly :(. Can someone answer this?
There's a table - Seller id, product id, warehouse id, quantity of products at each warehouse for each product as per each seller.
We have to list the Product Ids with Seller Id who has highest number of products for that product and the total number of units he has for that product.
I think I got confused because there were 3 keys in the table.
It's not quite clear which DBMS you are using currently. The below should work if your DBMS support window functions.
You can find count of rows for each product and seller, rank each seller within each product using window function rank and then use filter to get only top ranked sellers in each product along with count of units.
select
product_id,
seller_id,
no_of_products
from (
select
product_id,
seller_id,
count(*) no_of_products,
rank() over (partition by product_id order by count(*) desc) rnk
from your_table
group by
product_id,
seller_id
) t where rnk = 1;
If window functions are not supported, you can use correlated query to achieve the same effect:
select
product_id,
seller_id,
count(*) no_of_products
from your_table a
group by
product_id,
seller_id
having count(*) = (
select max(cnt)
from (
select count(*) cnt
from your_table b
where b.product_id = a.product_id
group by seller_id
) t
);
Don't know why having id columns would mess you up... group by the right columns, sum up the totals and just return the first row:
select *
from (
select sellerid, productid, sum(quantity) as total_sold
from theres_a_table
group by sellerid, productid
) x
order by total_sold desc
fetch first 1 row only
If I do not think about optimization, straight forward answer is like this
select *
from
(
select seller_id, product_id, sum(product_qty) as seller_prod_qty
from your_table
group by seller_id, product_id
) spqo
inner join
(
select product_id, max(seller_prod_qty) as max_prod_qty
from
(
select seller_id, product_id, sum(product_qty) as seller_prod_qty
from your_table
group by seller_id, product_id
) spqi
group by product_id
) pmaxq
on spqo.product_id = pmaxq.product_id
and spqo.seller_prod_qty = pmaxq.max_prod_qty
both spqi (inner) and sqpo (outer) give you seller, product, sum of quantity across warehouses. pmaxq gives you max of each product again across warehouses, and then final inner join picks up sum of quantities if seller has highest (max) of the product (could be multiple sellers with the same quantity). I think this is the answer you are looking for. However, I'm sure query can be improved, since what I'm posting is the "conceptual" one :)
How do i combine a SUM and MAX in a single query?
Lets say i have a orderrule:
ProductID \ Quantity
I Could say:
Select ProductID,SUM(Quantity) AS Sold
FROM Orderrule
GROUP BY ProductID
ORDER BY SUM(Quantity) Desc
However that would return all sales, and not just the most sold product (with quantity).
Try this
SELECT TOP(1)
*
FROM
(
Select
ProductID,
MAX(Quantity) As MaxQuantity,
SUM(Quantity) AS Sold
FROM Orderrule
GROUP BY ProductID
)AS X
ORDER BY Sold DESC
So there are two ways to do it - first to have a limit on the number of results, something likes:
select * from (your_select) where rownum = 1
the other one is to pick the one with the the highest value, which will require a subselect, something like:
having sum(quantity) =
(select max(sum_quan) from (select sum(Quantity) from orderrule group by Product_id))
SELECT TOP 1 ProductID, Sold FROM
(
SELECT ProductID, SUM(Quantity) AS Sold
FROM Orderrule
GROUP BY ProductID
) totals
ORDER BY Sold DESC