SQL to get overall average by aggregation - sql

I have a following table
employerid userid
123 1321
121 1567
126 1321
I want to write an SQL where I want overall average number of employerid per user id
For example
userid 1321 - 2 employerids (123 and 126)
userid 1567 - 1 employerid (121)
On an average (2 + 1) / 3 = 1.33
New to SQL. How do i write an SQL for this?

Related

Aggregate Function with Non-Aggregate Function In Select Command

I am exercising coding in MS.SQL Server. I have a small table below:
INV_NUM INV_AMOUNT
------- ----------
8000 235
8001 312
8002 528
8003 194
8004 619
I would like to write the query for all the invoices that will show:
the invoice number,
the invoice amount,
the average invoice amount, and
the difference between the average invoice amount and the actual invoice amount.
My code below:
SELECT I.INV_NUM,I.INV_AMOUNT,AVG(I.INV_AMOUNT) as AVERAGE,(AVG(INV_AMOUNT)-I.INV_AMOUNT) as DIFFER
FROM INVOICE I
GROUP BY I.INV_NUM,I.INV_AMOUNT;
The result in MS SQL did not generate the avg value, instead it shows INV_AMOUNT value in each row.
The result is :
INV_NUM INV_AMOUNT Average Differ
--------- ------------------------------------
8003 194 194 0
8000 235 235 0
8001 312 312 0
8002 528 528 0
8004 619 619 0
--------------- -------------------------------
I found if I have only one row in the table, it works fine.
Why this happened? Thanks!
I guess you want something like:
select
inv_num,
inv_amount,
avg(inv_amount) over() as average,
avg(inv_amount) over() - inv_amount as diff
from invoice
Your query is grouping your rows as separate groups. Instead you need to use a window function over a single group (using OVER).
Result:
inv_num inv_amount average diff
------- ---------- ------- ----
8000 235 377 142
8001 312 377 65
8002 528 377 -151
8003 194 377 183
8004 619 377 -242
You can use different solutions. As The Impaler mentioned you can use window functions. For diving deeper into this way of implementation you should read some tutorials about that.
Another way is using an CTE. You will first select the average invoice amount as own query. Afterwards you will use it in your "main" query. Looks like that:
WITH avg_inv AS
(
select avg(inv_amount) average
)
select
inv_num,
inv_amount,
(select average from avg_inv) as average,
(select average from avg_inv) - inv_amount as diff
from invoice;

Query with sum functions

for a little project(hobby purpose) i am building a C# application with a SQL database behind it.
However I am trying to build a query with a sum function which calculates values from a different table.
Here are the relevant tables and sample data
Hotel table
Id, Name Adress Zipcode Phone
1 Ankunding Group 90 Shelley Terrace 649-6326 86-(672)239-5855
2 Gerlach-Gutmann 50776 Bartillon Road 27109 CEDEX 33-(412)226-8055
3 Breitenberg-Smith 3289 Talisman Avenue 59762 86-(141)636-8780
4 Smitham-Marks 5 Veith Plaza 216282 7-(400)484-7233
5 Beatty LLC 3 Center Pass 940028 212-(310)974-4364
Reservation table
id, customerid, Startdate Enddate Amount of persons
1 163 2016-06-19 2017-04-30 4
2 172 2016-12-02 2016-08-18 5
3 162 2017-01-20 2017-04-08 3
4 66 2017-04-06 2017-01-07 2
5 104 2017-05-07 2016-09-10 2
RoomReservation table
Roomid, reservationid
3 53
3 198
4 178
5 172
5 218
Room table
id, hotelid, Roomnumber, price
1 1 1.01 268.83
2 1 1.02 201.28
3 1 1.03 126.64
4 1 1.04 122.56
5 1 1.05 217.41
Now I am trying to make a query to which gives me an overview off income per hotel. So for each hotel I want to get the reservations, and do amount of persons * the price of the room for each room in the hotel.
I've tried different things without success, I read somewhere that I needed to use a subquery but I have no idea how.
I want it to look like;
Hotelname1; income
Hotelname2; income
Hotelname3; income
Hotelname4; income
Hotelname4; income
Why can't you just do this:
SELECT
Hotel.Name,
SUM(Room.Price*Reservation.Amountofpersons)
FROM
Hotel
JOIN Room
ON Hotel.HotelId=Room.HotelId
JOIN RoomReservation
ON Room.RoomId=RoomReservation.RoomId
JOIN Reservation
ON RoomReservation.ReservationId=Reservation.ReservationId
GROUP BY
Hotel.Name
You can try it whit this query:
select hotel.name,sum(reservation.amount*room.price)
from hotel_table as hotel
inner join room_table as room on (hotel.hotelid=room.hotelid)
inner join roomreservation_table as room_reservation on (room.roomid=room_reservation.roomId)
inner join reservation_table as reservation on (room.reservationId=reservation.reservationid)
group by hotel.hotelid

Sequence / serial no in Oracle sql

My question is similar to how to generate Serial numbers +Add 1 in select statement
But I need the seq as below in Oracle sql
table 1 data:
facility store stop_seq
32 729 1
32 380 2
32 603 3
12 722 4
12 671 5
48 423 6
I need result as below:
facility res_seq
32 1
12 2
48 3
Here res_seq should be order by based on stop_seq in tabel 1
Please help
select facility, row_number() over(order by max(stop_seq)) res_seq
from your_tab group by facility;
ROW_NUMBER is explained in the link posted in the question
Analytic functions are performed after GROUP BY, so in this query the data is aggregated by facility and then row numbers are assigned

Access SQL - Select only the last sequence

I have a table with an ID and multiple informative columns. Sometimes however, I can have multiple data for an ID, so I added a column called "Sequence". Here is a shortened example:
ID Sequence Name Tel Date Amount
124 1 Bob 873-4356 2001-02-03 10
124 2 Bob 873-4356 2002-03-12 7
124 3 Bob 873-4351 2006-07-08 24
125 1 John 983-4568 2007-02-01 3
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
So, I would like to obtain only these lines:
124 3 Bob 873-4351 2006-07-08 24
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
Anyone could give me a hand on how I could build a SQL query to do this ?
Thanks !
You can calculate the maximum sequence using group by. Then you can use join to get only the maximum in the original data.
Assuming your table is called t:
select t.*
from t join
(select id, MAX(sequence) as maxs
from t
group by id
) tmax
on t.id = tmax.id and
t.sequence = tmax.maxs

Creating a new column based on data from an existing column

Consider a system to track repairs. I have a table with customer data and a common id key. I have a second table with a column to show which type of repair part was used on each id key and how many were used. Their definitions are below:
order_information
order_id | cust_last_name
465 Smith
899 Williams
512 Johnson
345 Fenton
122 Bowles
944 Cooper
parts_usage
order_id | part_type | part_quantity
465 Part 1 5
465 Part 2 4
899 Part 1 2
899 Part 2 8
899 Part 3 6
512 Part 3 1
345 Part 2 4
345 Part 3 5
122 Part 2 3
944 Part 1 2
I'd like to run a query for reporting that will return the part's pieces broken out like so:
order_id | Part 1 | Part 2 | Part 3 | Total
465 5 4 9
899 2 8 6 16
512 1 1
345 4 5 9
122 3 3
944 2 2
Is it possible to do this with a query so that my reports can show how many of each part was used on each repair ticket?
As you can see, each order_id can have multiple part types and unique quantities. I want to break the different part types (I have 3 total) into 3 separate columns with their totals listed by order_id.
select order_id, [Part 1], [Part 2], [Part 3], Total
from
(
select oi.order_id
, part_type
, part_quantity
, Total = sum(part_quantity) over (partition by oi.order_id)
from order_information oi
inner join parts_usage pu on oi.order_id = pu.order_id
) as parts
pivot
(
sum(part_quantity) for part_type in ([Part 1], [Part 2], [Part 3])
) as pvt
order by order_id
This works for me.
I have ordered the resultset by order_id as well; there doesn't appear to be a specific order in your example results but it is mentioned in the question details.
You can see the key is to combine the PIVOT with a SUM aggregate window function.
SQL Fiddle with demo.