Using Max and Sum in the same query - sql

I'm trying to get the the best selling product in all sales, and I'm using the following query:
SELECT Max(Sum(sold_mount)),
product_code
FROM sold_ items
GROUP BY product_code;
and it's returning "not a single-group group function"
it's possible to use max and sum in the same query?

I would recommend writing this as:
SELECT SUM(sold_mount), product_code
FROM sold_ items
GROUP BY product_code
ORDER BY SUM(sold_amount) DESC
FETCH FIRST 1 ROW ONLY;

Related

How to use SUM and MAX on the same column?

So I'm having an SQL table where I will need find out the product that has been purchased the most meaning that I need to do a SUM and a group by on all the quantity of the products:
SELECT PRODUCT_ID, SUM(QUANTITY) FROM PURCHASE GROUP BY PRODUCT_ID
However when I try to find the product with the maximum amount of purchases it gives me an error:
SELECT MAX(QUANTITY) FROM(SELECT PRODUCT_ID, SUM(QUANTITY) FROM PURCHASE GROUP BY PRODUCT_ID)
Any ideas?
Just order by and keep the top record only:
SELECT PRODUCT_ID, SUM(QUANTITY) SUM_QUANTITY
FROM PURCHASE
GROUP BY PRODUCT_ID
ORDER BY SUM_QUANTITY DESC
LIMIT 1
The actual syntax might vary accross RDBMS. The above would work in MySQL and Postgres.
In SQL Server, you would use SELECT TOP (1) ... ORDER BY SUM_QUANTITY DESC.
In Oracle >= 12c, you would use SELECT ... ORDER BY SUM_QUANTITY DESC FETCH FIRST ROW ONLY.
You also have to consider the possibilty of ties in the first position, for which there are different strategies depending on your requirement and RDBMS.

how to match a value with SQL max(count) function?

I have a orderLine table looks like this
I would like to know which pizza is the best seller, and the quantity of pizza sold.
I've tried query:
select sum(quantity), pizza_name from order_line group by pizza_name;
it returns
which is almost what I want, But when I start adding Max function, it could not match the pizza name with the total quantity of pizza sold
For example:
select MAX(sum(quantity)), pizza_name from order_line group by pizza_name;
it returns following error:
"not a single-group group function"
I guess I could achieve this by using a sub-query, but I have no idea how to do this.
You don't need max for this. If you only want one pizza, then you can use order by and fetch first 1 row only (or something similar such as limit or top):
select sum(quantity), pizza_name
from order_line
group by pizza_name
order by sum(quantity)
fetch first 1 row only;
Or, if you want all such pizzas, use rank():
select p.*
from (select sum(quantity) as quantity, pizza_name,
rank() over (order by sum(quantity) desc) as seqnum
from order_line
group by pizza_name
) p
where seqnum = 1;
Both of the queries give the same desired result
SELECT PIZZA_NAME,
SUM(QUANTITY) "Total Quant"
FROM Order_line
GROUP BY PIZZA_NAME
ORDER BY "Total Quant" DESC
FETCH FIRST 1 row only;
SELECT PIZZA_NAME, "Total Quantity" FROM (
SELECT PIZZA_NAME,SUM(QUANTITY) "Total Quantity", RANK() OVER (ORDER BY SUM(QUANTITY) DESC) T FROM Order_line GROUP BY PIZZA_NAME
) query1 where query1.T=1 ;
You group by pizza_name to get sum(quantity) per pizza_name.
Then you aggregate again by using MAX on the quantity sum, but you don't specify which of the three pizza names to have in the result. You need an aggregate function on pizza_name as well, which you don't have. Hence the error.
If you want to use your query, you must apply the appropriate aggregation function on pizza_name, which is KEEP DENSE_RANK FIRST/LAST.
select
max(sum(quantity)),
max(pizza_name) keep (dense_rank last order by sum(quantity))
from order_line
group by pizza_name;
But on one hand Gordon's queries are more readable in my opinion. And on the other this double aggregation is Oracle specific and not SQL standard. Unexperienced readers may be confused that the query produces one result row in spite of the GROUP BY clause.

SQL COUNT function to find commonality

The question I'm facing is as follows: list the first letters of the product names and their totals. Only display the letter and count if there are 3 or more products beginning with that letter of the alphabet.
Clearly the query requires the use of the COUNT aggregate, but I am spinning my wheels looking at this. How do I write this query?
expected output:
ProductName Total
C 9
G 11
ETC...
I'm assuming I need a SUBSTRING in my select statement
SELECT SUBSTRING(ProductName,1,1) AS ProductName,
COUNT(ProductName) AS Total
FROM Products
But using WHERE with a count function will give me an aggregate error is SQLServer2012?
You cannot use aggregate function's in where clause to filter the result
To filter the group's you have to use having clause instead of where clause. Try this
SELECT SUBSTRING(ProductName,1,1) AS ProductName,
COUNT(ProductName) AS Total
FROM Products
group by SUBSTRING(ProductName,1,1)
having COUNT(ProductName) >=3
You just need a proper group and having clause:
SELECT
LEFT(ProductName, 1) AS ProductName,
COUNT(*) AS [Total]
FROM Products
GROUP BY
LEFT(ProductName, 1)
HAVING COUNT(*) >= 3

Summary Query to Sum Operations not working

SELECT price,total_price,SUM(mount) As TotalAmount
FROM sales
group by [date]
is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
You cannot select fields in the SELECT part which is not a part of an Aggregated function or specified in the the GROUP BY clause when using GROUP BY.
You can select "mount" because it's aggregated (SUM), but not price or total_price because they're not aggregated nor part of your group by date
You will need to either change your group by functionality, or the select part.
You have to group by the remaining tables that are not a function, therefore:
SELECT price,total_price,SUM(mount) As TotalAmount
FROM sales
Group by price,total_price
Order by date

How can I fix my Oracle 11G SQL query?

I can't figure out what I am doing wrong with my query here.
SELECT ORDER#, SUM(PAIDEACH * QUANTITY) AS TOTAL
FROM ORDERITEMS
WHERE TOTAL > 39.9
GROUP BY ORDER#
ORDER BY TOTAL DESC;
This is the error I keep getting:
"TOTAL": invalid identifier
Since you want to have a predicate on your aggregate function, you can use a HAVING clause
SELECT ORDER#, SUM(PAIDEACH * QUANTITY) AS TOTAL
FROM ORDERITEMS
GROUP BY ORDER#
HAVING SUM(PAIDEACH * QUANTITY) > 39.9
ORDER BY TOTAL DESC;
If you want to use an alias in your WHERE clause then you can place your query inside of another SELECT:
SELECT *
FROM
(
SELECT ORDER#, SUM(PAIDEACH * QUANTITY) AS TOTAL
FROM ORDERITEMS
GROUP BY ORDER#
) x
WHERE x.TOTAL > 39.9
ORDER BY x.TOTAL DESC;
order by 2 desc (numeric references to columns start with 1)
There is no need to write nested queries or even putting a having clause to your query. Just refer to the column with a numeral, but don't forget to change it when you change the query ;-)