I am trying to set up a subquery - sql

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;

Related

Multiple Aggregation in SQL

loan_no loan_amt contact date customer_id salesman_id
I have the following table. I need to somehow get the average of loan_no and the average of loan_amt for the people with more than one loan_no. I need to somehow plug in the avg and count functions.
I am seriously struggling with that. I was also thinking of a pivot function.
I would really appreciate it if someone can suggest a SQL code
My efforts so far:
select count (loan_no), tcustomer_id
from table
group by customer_id
having count (loan_no) > 1
Now I just do not know how to also include the avg function.
Not sure why do you need average Loan_no but you can still get it through -
select customer_id, avg(loan_no), avg(loan_amt)
from (select *, count(*) over(partition by customer_id) cnt
from table)
where cnt > 1
group by customer_id
You can use two levels of aggregation:
select avg(num_loans), sum(total) / sum(num_loans)
from (select customer_id, count(*) as num_loans, sum(loan_amt) as total
from table
group by customer_id
) t
where num_loans > 1;

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. :)

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

get row with max from group by results

I have sql such as:
select
c.customerID, sum(o.orderCost)
from customer c, order o
where c.customerID=o.customerID
group by c.customerID;
This returns a list of
customerID, orderCost
where orderCost is the total cost of all orders the customer has made. I want to select the customer who has paid us the most (who has the highest orderCost). Do I need to create a nested query for this?
You need a nested query, but you don't have to access the tables twice if you use analytic functions.
select customerID, sumOrderCost from
(
select customerID, sumOrderCost,
rank() over (order by sumOrderCost desc) as rn
from (
select c.customerID, sum(o.orderCost) as sumOrderCost
from customer c, orders o
where c.customerID=o.customerID
group by c.customerID
)
)
where rn = 1;
The rank() function ranks the results from your original query by the sum() value, then you only pick those with the highest rank - that is, the row(s) with the highest total order cost.
If more than one customer has the same total order cost, this will return both. If that isn't what you want you'll have to decide how to determine which single result to use. If you want the lowest customer ID, for example, add that to the ranking function:
select customerID, sumOrderCost,
rank() over (order by sumOrderCost desc, customerID) as rn
You can adjust you original query to return other data instead, just for the ordering, and not include it in the outer select.
You need to create nested query for this.
Two queries.