Average Quantity with subselect - sql

I have following table, where OrderID is unique and ordernumber is not unique:
OrderID|Ordernumber|ProductID|Quantity
1|1234|10|12|
2|1234|55|10|
3|1234|55|22|
4|1029|99|44|
1.I want complete table and using subselect to get average quantity per ordernumber , but as far I know subselect only allows one Column.
And another query where the avg is per Ordernumber and per Prod
OrderID|Ordernumber|ProductID|AVGQuantity
1|1234|10|14,7|
2|1234|55|14,7|
3|1234|55|14,7|
4|1029|99|44|
Outcome should be:
OrderID|Ordernumber|ProductID|AVGQuantity
1|1234|10|11|
2|1234|55|11|
3|1234|55|22|
4|1029|99|44|
Thanks in advance.

This answers the original version of the question.
You can use window functions:
select t.*,
avg(quantity) over (partition by ordernumber) as avg_quantity
from t;

Related

how to extract MAX value with multiple conditions in SQL

I'm dumping an SQL sales/order table and running the following Excel array command to find the highest value, for a particular order:
{ =MAX(IF([ORDER]=[#[ORDER]];IF([PRODUCT]=[#PRODUCT];[QTY]))) }
This checks, for any rows belonging to the same order, for the same product, what the highest QTY listed is. But being an Arry formula, it freezes my Excel for many minutes.
Can I do something similar directly in SQL?
You can get MAX value with aggregate function MAX and apply condition with WHERE like below.
SELECT MAX(QTY)
FROM TABLE
WHERE [ORDER] = #ORDER AND [PRODUCT] = #PRODUCT
And if you want ORDER and PRODUCT wise MAX QTY value for all ORDER and PRODUCT then use GROUP BY like below.
SELECT MAX(QTY)
FROM TABLE
GROUP BY [ORDER], [PRODUCT]
If you want the value per row, then you would use window functions:
select t.*, max(qty) over (partition by order, product)
from t;
Note: order is a very bad name for a column because it is a SQL keyword. If that is the real name, you need to escape it.

How to select MAX from AVG?

I'm practicing for my SQL exam and I can't figure out the following question:
"Of the average amount paid per customer, show the highest amount."
So to retrieve the average amount paid, I would do the following:
SELECT AVG(Amount) AS 'Average amount paid'
FROM Payment;
Then I would like to retrieve the highest average amount out of this list of averages. I thought the following would do the trick:
SELECT MAX(AVG(Amount)) AS 'Highest average amount paid'
FROM Payment;
This doesn't seem to work. I get the following error:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
I would like some help with this. What is the correct way to approach this? Thank you in advance.
In SQL Server, you can order the records and use TOP 1 to keep only the record that has the highest amount:
SELECT TOP 1 Customer_id, AVG(Amount) AS [Average amount paid]
FROM Payment
GROUP BY customer_id
ORDER BY [Average amount paid] DESC;
Note: for this query to make sense, you need a GROUP BY clause. Without it, it would just return one record, with the average of payments within the whole table.
Try using a sub-query:
SELECT MAX(src.cust_avg) AS "Highest average amount paid"
FROM (
SELECT cust_id, AVG(Amount) AS cust_avg
FROM Payment
GROUP BY cust_id -- Get averages per customer
) src
;
To get the "per customer" averages first, you need include something like GROUP BY cust_id.
SQL Fiddle
Use order by:
select customer, avg(amount)
from payment
group by customer
order by avg(amount) desc
fetch first 1 row only;
The fetch first (although standard) is not supported by all databases, so you should use the version appropriate for your database.
In SQL Server, you would use either select top (1) or offset 0 fetch first 1 row only (the offset is not optional, alas).
There are also databases where avg() on an integer returns an integer. If amount is an integer and your database does this, then use avg(amount * 1.0).

Count(), max(),min() fuctions definition with many selects

Lets say we have a view/table hotel(hotel_n,hotel_name, room_n, price). I want to find the cheapest room. I tried group by room_n, but I want the hotels name (hotel_name) to be shown to the board without grouping it.
So as an amateur with sql(oracle 11g) I began with
select hotel_n, room_n, min(price)
from hotel
group by room_n;
but it shows the error: ORA-00979: not a GROUP BY expression. I know I have to type group by room_n, hotel_n, but I want the hotel_n to be seen in the table that I make without grouping by it!
Any ideas? thank you very much!
Aggregate functions are useful to show, well, aggregate information per group of rows. If you want to get a specific row from a group of rows in relation to the other group members (e.g., the cheapest room per room_n), you'd probably need an analytic function, such as rank:
SELECT hotel_n, hotel_name, room_n, price
FROM (SELECT hotel_n, hotel_name, room_n, price
RANK() OVER (PARTITION BY room_n ORDER BY price ASC) rk
FROM hotel) t
WHERE rk = 1

Whats the difference between these two SQL queries?

Question: Select the item and per unit price for each item in the items_ordered table. Hint: Divide the price by the quantity.
1.
select item, sum(price)/sum(quantity)
from items_ordered
group by item;
2.
select item, price/quantity
from items_ordered
group by item;
Have a look at the resultis for flashlights. First one shows average price correctly but 2nd one only takes 28/4 and shows 7, ignoring the 4.5 few rows down. Someone please explain why this is the case.
The used table data from an external website.
SUM() is a group function - so that essentially says go get me all the price and quantities by item, and add them all up to return them in one row.
MySQL is quite forgiving when grouping things and will try to retrieve a rowset (which is why your second example returns something - albeit wrong).
Generally, if you are GROUPing columns (items in your exmaple), you need to return one row per column (item).
Try running the SQL below to see what that looks like.
SELECT item
, SUM(price) AS sum_price
, SUM(quantity) AS sum_quantity
, COUNT(*) AS item_count
, SUM(price) / SUM(quantity) AS avg_price_per_quant
FROM items_ordered
GROUP BY item
ORDER BY item ASC
The first query returns the average price for that item, the second query returns the price for the first item it encounters. This only works in MySQL, the second query would error in SQL Server as no aggegrate function is used. See this post for more details Why does MySQL allow "group by" queries WITHOUT aggregate functions?.

SQL grouping results in a select

My SQL table "offers" contains offers users make for products (product_ID, customer_ID, offer).
In my admin page, I want to list the products for which at least one offer exists and show the total offers existing for it.
For example,
PRODUCT #324 Total offers: 42
PRODUCT #99 Total offers: 1
etc.
My guess would be to combine a
SELECT DISTINCT product_ID FROM offers...
And in a second query, to SELECT COUNT(*) FROM offers WHERE product_ID=...
Is it the most efficient way to achieve this, or is there a way to make it inside a single query?
You can do this in one query which will get the count by grouping by the product_id:
SELECT product_ID, COUNT(*)
FROM offers
GROUP BY product_ID
As bluefeet already answered, you achieve it in single query by using group by.
(group by demo)
Another thing to mention is the order by,
select
product_id as id,
count(*) as totals
from
t
group by product_id
order by totals;
If you want to sort with the totals of hits, or if you want to sort by product_id etc.
sqlfiddle