Average grade of student temporary table in SQL Server - sql

I have a database with the following tables:
Students_T (SNo, SDedc, SAddress)
Courses_T (CNo, CDesc)
CoursesRegister_T (CRNo, CR_CNo, CR_SNo, CRGrade)
I need to represent the following data:
For each student show:
Student desc, Course desc, Course grade, Grades average
And I need to do this for every course that the student register in.
For example:
if student A is registered to course B and his grade is 90
and he's also registered to course C and his grade is 70, I suppose to get the following table:
A B 90 80
A C 70 80
The important thing is that I need to use temporary tables with SELECT INTO syntax and I can't figure it out.
I'm using SQL Server.
Someone know how to do that?
EDIT:
I already did this:
select CR_ST_No, ST_Desc, CR_Desc, CR_Grade
into #Grades
from Students_T
left join CoursesRegister_T on CR_ST_NO = ST_No
where CRS_Desc is not null
select *
from #Grades
drop table #Grades
and it's giving me table with all data I need except the average.
When I try to change the row select * to select *, avg(CR_Grade)
it can't execute.

This is a typical use case for a Window Function. You haven't provided any sample data and I can't test it right now, but something like that should work:
SELECT s.SDedc, c.CDesc, r.CRGrade, AVG(r.CRGrade) OVER (PARTITION BY s.SNo) AS average_grade
FROM Students_T AS s
LEFT JOIN CoursesRegister_T AS r ON r.CR_SNo = s.SNo
LEFT JOIN Courses_T AS c ON r.CR_CNo = c.CNo;

From your question and the subsequent comments, you need to change your select-statement to include a group by clause.
Please read through the MSDN SELECT (Transact-SQL) article as to how a select statement is structure, with explanations and examples of each section.
The reason you are getting your error message is that the AVG is an aggregate function and so requires that all columns that are not part of the aggregate, to be included into the group by clause of your select statement.

Related

SQL SELECT FOR SALES WITH 'COUNT' FROM ANOTHER TABLE

I have two tables. The first one is for sales (name's table is 'ventas') and the other one, for detailed articles by sale (the name is 'ventaArticulos'). Basically, the last one contains all the articles that were sold.
Those are related by the columns ventas.id_venta and ventaArticulos.id_ventaArticulo
Basically, the idea is to make an SQL SELECT for the first table (ventas) for example, getting the columns 'fecha' and 'importe' but also, perform a 'count' with the total of registers that are in the second table related by sale. (ventas.id_venta and ventaArticulos.id_ventaArticulo)
hope to be clear enough and can help me!
SQL to try to clarify (Obviously it doesn't work):
SELECT ventas.fecha, ventas.importe, count(ventaArticulos.id_codigoArt)
FROM ventas JOIN
ventaArticulos
ON ventaArticulos.id_ventaArticulo = ventas.id_venta
Thanks!
I would recommend to use table alise that could be easier to follow & you forgot to include GROUP BY Clause
SELECT v.fecha, v.importe, count(va.id_codigoArt) counts
FROM ventas v -- Use alise v entire the query instead of table_name
INNER JOIN ventaArticulos va ON va.id_ventaArticulo = v.id_venta
GROUP BY v.fecha, v.importe;
SELECT v1.fecha, v1.importe, count(v2.id_codigoArt)
FROM ventas v1 , ventaArticulos v2
where v1.id_ventaArticulo= v2.id_venta
group by v1.fecha, v1.importe
having count(*) > 1

SQL - Not sure if I should use joins to resolve this query

I have the following question presented to me:
"Write a SQL command to display for each student who has an average result of greater than 60, the student’s name, the total number of attempts the student has had at all exams, and the student’s average result."
The tables I am working with for this are:
Mark, with fields examID(PK), studentID(PK), result, occurred, noOfAttempts
And Student with the fields id(PK) and Name.
The field StudentID in mark is also a foreign key to Student.
Anyways this is what I've come up with so far:
SELECT S.name, AVG(M.RESULT) FROM STUDENT S, MARK M
WHERE S.ID = (
SELECT studentID FROM
MARK
WHERE 60 <
(SELECT AVG(result) from MARK));
But it is igiving me a "not a single group function" error. I've tried using some other joins but that also resulted in a whole ton of errors so I'm pretty sure I did those wrong.
At this point I am nearly completely lost. I know that the "deepest" subquery will return me the student ID's that have an average result bigger than 60, but when I try to return all student ID's that match that particular ID it doesnt work. I'm also not sure how to count the total no. of attempts in this query so I didnt even attempt that for now.
Table data:
You can try something like that:
SELECT
S.name, SUM(M.noOfAttempts) AS attempts, AVG(M.RESULT) AS result
FROM
STUDENT S
INNER JOIN
MARK M ON (S.ID = M.studentID)
GROUP BY
S.ID, S.name
HAVING
AVG(M.RESULT) > 60

SQL Sum with Sub Query?

Thanks for any help in advance, I can't wrap my SQL skills around this one...
I have two tables like this:
Settings
Customerid ViewerLimit
1 50
2 50
Distribution
Customerid ServerIP
1 stream3
1 stream4
2 stream3
I want to calculate the load on each server. A customer divides the load if they have more than one server, so here customer 1 puts a load of 25 on each server. The result I'm trying to get is this:
ServerIP Load
stream3 75
stream4 25
I tried to do a sum function similar to this:
sum(viewerlimit/(count # of servers)) as load group by serverip
But I can't do a sub query within a sum function. There are many customers and possibly many servers per customer so it will become too complex to do manually. I appreciate any input.
Here is uninspired version with count in derived table:
select serverip, sum (viewerlimit/cast (ServerCount as float)) Load
from
(
select customerid, count(*) ServerCount from distribution group by customerid
) a
inner join settings
on a.customerid = settings.customerid
inner join distribution
on settings.customerid = distribution.customerid
group by serverip
Sql Fiddle to play around
UPDATE - an attempt at explanation
Derived tables are used to produce ad-hoc result sets that can be joined to main body of a query. It is placed in from clause and enclosed in parenthesis. You can use anything an ordinary select can use, top, order by, aggregate functions etc. The only thing you cannot use is correlation to a table in main body. Oh, and CTE. Derived table must be aliased.
In previous sample derived table 'a' selects counts of servers by customerid. Main body sees it as a table with CustomerId and ServerCount columns, ready to be used as any column from all listed tables. A join on customerid is performed between settings and 'a'. As this is 1:1 relation (both tables produce single row given a customerid), no duplication occurs.
How about doing a count of servers in a sub query and assign that to a query variable and then use that query variable inside the sum function?
select d.serverip, sum(s.viewerlimit/d.devider)
from (
select customerid, serverip, COUNT(serverip) over (partition by customerid) servercount
from distribution
) d
join settings s
on s.customerid=d.customerid
group by d.serverip

SQL Database SELECT question

Need some help with an homework assignment on SQL
Problem
Find out who (first name and last name) has played the most games in the chess tournament with an ID = 41
Background information
I got a table called Games, which contains information...
game ID
tournament ID
start_time
end_time
white_pieces_player_id
black_pieces_player_id
white_result
black_result
...about all the separate chess games that have taken place in three different tournaments ....
(tournaments having ID's of 41,42 and 47)
...and the first and last names of the players are stored in a table called People....
person ID (same ID which comes up in the table 'Games' as white_pieces_player_id and
black_pieces_player_id)
first_name
last_name
...how to make a SELECT statement in SQL that would give me the answer?
sounds like you need to limit by tournamentID in your where clause, join with the people table on white_pieces_player_id and black_pieces_player_id, and use the max function on the count of white_result = win union black_result = win.
interesting problem.
what do you have so far?
hmm... responding to your comment
SELECT isik.eesnimi
FROM partii JOIN isik ON partii.valge=isik.id
WHERE turniir='41'
group by isik.eesnimi
having count(*)>4
consider using the max() function instead of the having count(*)> number
you can add the last name to the select clause if you also add it to the group by clause
sry, I only speak American. What language is this code in?
I would aggregate a join to that table to a derived table like this:
SELECT a.last_name, a.first_name, CNT(b.gamecount) totalcount
FROM players a
JOIN (select cnt(*) gamecount, a.playerid
FROM games
WHERE a.tournamentid = 47
AND (white_player_id = a.playerid OR black_player_id = a.playerid)
GROUP BY playerid
) b
ON b.playerid = a.playerid
GROUP BY last_name, first_name
ORDER BY totalcount
something like this so that you are getting both counts for their black/white play and then joining and aggregating on that.
Then, if you only want the top one, just select the TOP 1

Retrieving alternate attribute values in GROUP BY query?

Let me explain what I mean with that question:
Lets say I have to tables like these:
customers
id customer location
1 Adam UK
2 Pete US
values
id value
1 10
1 7
2 3
2 41
Let's ignore here for a moment that that (and the following query) wouldn't make a lot of sense. It's meant as a simplified example.
Now, if I run this query
SELECT id, customer, value FROM customers INNER JOIN values GROUP BY id
I should get this result (distinct by id)
id customer value
1 Adam 10
2 Pete 3
What I would like to be able to do is get that to use it in a search result list, but for actual displaying of the results I'd like to do something like this:
Customer: Adam
Values: 10, 7
So, basically, while I need to have a result set that's distinct for the ID, I'd still like to somehow save the rows dropped by the GROUP BY to show the values list like above. What is the best way to do this?
Look at http://mysql.com/group_concat - which only will work in MySql.
Better link: http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_group-concat
Technically, the following is not valid SQL even though MySQL allows it:
Select customers.id, customers.customer, values.value
From customers
Inner Join values
On values.id = customers.id
Group By customers.id
The SQL spec requires that every column in the Select clause be referenced in the Group By or in an aggregate function. However, given what you said later in your post, what I think you want is GROUP_CONCAT as first mentioned by Erik (+1) which is a function specific to MySQL:
Select customers.customer, Group_Concat(values.value)
From customers
Inner Join values
On values.id = customers.id
Group By customers.customer