How can I fix my Oracle 11G SQL query? - sql

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 ;-)

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.

I am trying to set up a subquery

I am trying to see how I can write a subquery. I have a table called supplier. The fields are supplierid, name, ordervalue and orderid. I need to write a query that will produce all the suppliers that has order ordervalue > 1000000 more than 10 times.
select name, count(*)
from (select orderid from supplier where ordervalue >1000000 group by
orderid)
where count(*) > 10
group by name;
ANSI way of writing this query which should work in most RDBMS (at least in SQL Server and in Oracle):
SELECT name, COUNT(orderid)
FROM supplier
WHERE ordervalue > 1000000
GROUP BY name
HAVING COUNT(orderid) > 10;

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.

Which customer has placed most orders. SQL query

I'm trying to query my database for my class to find out which customer has placed the most orders. The table I'm searching is a three attribute table that has the customerID, orderID, and the placedDate.
The query I thought would work is:
select cid from placed order by sum(oid);
But I keep getting an error saying cid is "not a single-group group function" the oid is the primary key and is a foreign key that references another table. Is that what the issue is?
If you want to count the number of orders you should do a count instead of a SUM:
SELECT cid,COUNT(*)
FROM placed
GROUP BY cid
ORDER BY COUNT(*) DESC
This will give you the list of customers and their respective number of orders, ordered by the number of orders descendent.
If you want just the customer with most orders, you have to limit the number of records to the first one. For that, you have to tell what DBMS you use, since it varies with the DBMS the way you limit the query to the first one (ex: mysql is LIMIT 1, sql-server is TOP 1):
In Oracle, you can do:
SELECT * FROM (
SELECT cid,COUNT(*)
FROM placed
GROUP BY cid
ORDER BY COUNT(*) DESC
) a
WHERE rownum = 1
In case the there are one or more customers having maximum orders:
select * from orders o, customer c where o.cusId = c.cusId and o.cusId IN (select cusId from orders group by cusId having count(*) = (select count(*) from orders or group by or.cusId order by count(*) desc limit 1));
This solution is for MySQL, as I have used LIMIT. It can be changed as per the DBMS.
I also used = in the second query since LIMIT does not work with IN.

SQL Server 2012 Group only by one column

I need to group only by one column
SQL Server 2012 query:
SELECT OrderID,Status,DateEdited
FROM orders
WHERE Status='Pending'
GROUP BY OrderID,Status,DateEdited
and the result is:
As you can see there are duplicate OrderId column values.
Works but it groups by OrderId,Status,DateEdit but what I need is that the OrderId would be unique in the results can I have something like:
SELECT OrderID,Status,DateEdited
FROM orders
WHERE Status='Pending'
GROUP BY OrderID
You have to use an aggregate function for status and DateEdited, to get distinct valeus for each grouped ORDERID. You can also use the ranking functions to do so like this:
WITH CTE
AS
(
SELECT
OrderID,
Status,
DateEdited,
ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY DateEdited DESC) rownum
FROM orders
WHERE Status='Pending'
)
SELECT
OrderID,
Status,
DateEdited
FROM CTE
WHERE rownum = 1;
This will give you distinct ORDERIDs. But which status and DateEdited to return for each grouped ORDERID?
Then you can do like this,
SELECT OrderID,'Pending' as Status,max(DateEdited)
FROM orders
WHERE Status='Pending'
GROUP BY OrderID
If you dont want to loose any record then you can go for
GROUP_CONCAT()
SELECT OrderID,'Pending' as Status,GROUP_CONCAT(DateEdited)
FROM orders
WHERE Status='Pending'
GROUP BY OrderID
Note: Am not sure whether you GROUP_CONCAT in sqlserver Incase it's not there
go for a function like that. :)