How to get the largest value of a column in table? - sql

I have the following table:
fileId, studentId,
Given a particular studentId, how can I get the largest fileId that is in the table ?
I saw this other query :
SELECT row
FROM table
WHERE id=(
SELECT max(id) FROM table
)
This would give the row where id is the largest. But what about the largest id for a given student id ? Is it better to match the student in the inner query or outer query ?

if you need the whole row:
select * from table where studentId = your_known_id order by fileId desc limit 1

This seems simplest:
SELECT studentId, MAX(ID)
FROM TableA
GROUP BY studentId
OR With filtering options:
WITH CTE AS
(
SELECT studentId, MAX(ID)
FROM TableA
GROUP BY studentId
)
SELECT * FROM CTE WHERE studentId ...

Try this:
SELECT *
FROM (
SELECT
id,
ROW_NUMBER () OVER (PARTITION BY studentId ORDER BY id desc) rnk
FROM table) a
WHERE a.rnk = 1;

... what about the largest id for a given student id
SELECT MAX(fileId)
FROM table
WHERE studentId = 123
Where 123 is the student if you want to filter on.
say there are three rows with studentId =3, but with fileId's = {4,5,6}, how do i get the row {fileId,studentId} = {6,3}
SELECT MAX(fileId), studentId
FROM table
WHERE studentId = 3
GROUP BY studentId

I think this code works as well
SELECT max(field) from table_name where studenId = <someID>

Related

Select Person with only one value in the column

I can't correctly write a query.
I need to select a person who has only one value in the column. For example,
select * (
select PersonID, sum(TotalAmount)
from Table1
group by PersonID
HAVING sum(TotalAmount) = 0 )
where Group = A
It means that I would select all customers that belong to ONLY 'A' group...
Could someone help me?
If you want the persons with only one value, then having count(*) = 1 comes to mind:
select personid
from table1
group by personid
having count(*) = 1;

Best way to select max value of each group on top of other query

Does someone know how to select max value of each group on top of other query?
Example table:
Class Exam Grade
Math1 Mid 1
Math2 Mid 2
Math1 Final 1
Say I have the first query like this:
SELECT *
FROM table
WHERE Class = 'Math1'
Now using the resulting table I want to group by Exam and keep only the row with the max grade:
SELECT view1.*
FROM
(SELECT *
FROM table
WHERE Class = 'Math1') AS view1, view2
WHERE view1.Exam = view2.Exam
AND view1.Grade > view2.Grade
The problem I can't give 2 alias for the same table. So view1 and view2 wont work the way is written. Is there a best practice?
Thank you!
UPDATE:
Thank you all for the answers, it helped me but I was trying to remember the following solution with the WITH:
WITH view AS (SELECT *
FROM table
WHERE Class = 'Math1)
SELECT view1.*
FROM view view1, view view2
WHERE view1.Exam = view2.Exam
AND view1.Grade > view2.Grade
why not:
SELECT distinct max(grade) over (partition by exam), exam
FROM table
WHERE Class = 'Math1'
If you want the row with the highest grade, use order by and limit:
SELECT *
FROM table
WHERE Class = 'Math1'
ORDER BY grade DESC
LIMIT 1;
You can use row_number to select the row with the highest grade per exam for all Math classes
select * from (
select *,
row_number() over (partition by exam, Class order by grade desc) rn
where Class = 'Math1'
) t where rn = 1
If you want to include ties for the highest grade then use rank instead of row_number
You can use distinct on to select row with max grade for each exam:
select distinct on (exam) exam,
t.*
from (
-- Your query here
select *
from table
where class = 'Math1'
) t
order by exam,
grade desc;
Or directly:
select distinct on (exam) exam,
t.*
from table
where class = 'Math1'
order by exam,
grade desc;

Select rows of joined values using MAX

Consider the following schema.
Student:
StudentID uniqueidentifier
Name varchar(max)
FKTeacherID uniqueidentifier
TestScore:
TestScoreID uniqueidentifier
Score int
FKStudentID uniqueidentifier
My goal is to write a query that yields each teacher's highest test score and the student that achieved it. Returning the teacher's id (Student.FKTeacherID), the score that was achieved (TestScore.Score) and the student that achieved it (Student.Name).
I can write something like this to get the first two required columns:
SELECT FKTeacherID, MAX(Score) MaxScore
FROM Student
JOIN TestScore on FKStudentID = StudentID
GROUP BY FKTeacherID
But I can't obtain the relevant Student.Name without adding it to the group by clause, which would change the result set.
If I'm understanding correctly, one option is to use row_number() -- here's an example with a common-table-expression:
with cte as (
select s.fkteacherid,
ts.score,
s.name,
row_number() over (partition by s.fkteacherid order by ts.score desc) rn
from student s
inner join testscore ts on s.studentid = ts.fkstudentid
)
select fkteacherid, score, name
from cte
where rn = 1
The basic idea is to group by fkteacherid, ordering by the score desc within each group, and taking the first record from each group.
UPDATE
Please try the updated query if you might:
SELECT
FKTeacherID, Name, Score
FROM
Student
JOIN TestScore on FKStudentID = StudentID
JOIN
(
SELECT
B.FKTeacherID AS TeacherID, MAX(A.Score) MaxScore
FROM
Student B
JOIN TestScore A on A.FKStudentID = B.StudentID
GROUP BY
B.FKTeacherID
) As TeachersMaxScore
ON TeachersMaxScore.TeacherID = FKTeacherID
AND TeachersMaxScore.MaxScore = Score

Sum of Highest 5 numbers in SQL Server 2000

I am having a problem in query some data from database. My table is given below:
What i need is that sum of 5 highest total_marks from the table for each student.
Although i tried the code given below, but it is not returning what i expected.
SELECT s.studentid, SUM(s.total_marks)
FROM students s
WHERE s.sub_code IN (SELECT TOP 5 sub_code
FROM students a
WHERE a.studentid = s.studentid
ORDER BY total_marks DESC)
GROUP BY studentid
Please help me guys. Thanking you advance.
You query could work if there's unique/primary key on (studentId, subcode). At the moment, the query returns 6 records instead of 5 for studentId = 1, for example, beause of duplicate subcode 303.
Usually table should have a unique key, may be you can add incremental id to rewrite your query like:
select s.*
from students as s
where
s.id in (
select top 5 a.id
from students as a
where a.studentId = s.studentId
order by a.total_marks desc
);
Or, if you have unique combinations of (studentId, subcode, total_marks), you can use query like this:
select s.*
from students as s
where
exists (
select *
from (
select top 5 a.subcode, a.total_marks
from students as a
where a.studentId = s.studentId
order by a.total_marks desc
) as b
where b.subcode = s.subcode and b.total_marks = s.total_marks
);
sql fiddle demo
First you should select top 5 grades for each student -
select row_number() over (partition by studentid order by total_marks desc) as rank,
studentid,
total_marks
from students
where rank <= 5
from there you'll be able to use this as a subquery, and use group_by and sum:
select studentid, sum(total_marks)
from
(
select row_number() over (partition by studentid order by total_marks desc) as rank,
studentid,
total_marks
from students
where rank <= 5
) t
group by studentid
This isn't ideal, but the method you started to use requires a primary key column. You can simulate one with a temp table since SQL 2000.
CREATE TABLE #temp (
StudentID INT,
total_marks INT,
ID INT Identity(1,1)
)
INSERT INTO #temp (
StudentID,
total_Marks
)
Select
StudentID,
total_marks
FROM Students
SELECT s.studentid, SUM(s.total_marks)
FROM #temp s
WHERE s.ID IN (SELECT TOP 2
a.ID
FROM #temp a
WHERE a.studentid = s.studentid
ORDER BY total_marks DESC)
GROUP BY studentid
I think SQL 2000 may have a slightly more compact syntax for this, but SQL Fiddle won't let me test versions that old.
Please test this carefully. You will be dumping this entire table to a temp table and that's almost always a bad idea.
Also, ensure that there is some combination of fields not including the total that uniquely identifies a row, or consider adding a surrogate key column to the table.
SQL Fiddle Demo

SQL query to return only 1 record per group ID

I'm looking for a way to handle the following scenario. I have a database table that I need to return only one record for each "group id" that is contained within the table, furthermore the record that is selected within each group should be the oldest person in the household.
ID Group ID Name Age
1 134 John Bowers 37
2 134 Kerri Bowers 33
3 135 John Bowers 44
4 135 Shannon Bowers 42
So in the sample data provided above I would need ID 1 and 3 returned, as they are the oldest people within each group id.
This is being queried against a SQL Server 2005 database.
SELECT t.*
FROM (
SELECT DISTINCT groupid
FROM mytable
) mo
CROSS APPLY
(
SELECT TOP 1 *
FROM mytable mi
WHERE mi.groupid = mo.groupid
ORDER BY
age DESC
) t
or this:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY groupid ORDER BY age DESC) rn
FROM mytable
) x
WHERE x.rn = 1
This will return at most one record per group even in case of ties.
See this article in my blog for performance comparisons of both methods:
SQL Server: Selecting records holding group-wise maximum
Use:
SELECT DISTINCT
t.groupid,
t.name
FROM TABLE t
JOIN (SELECT t.groupid,
MAX(t.age) 'max_age'
FROM TABLE t
GROUP BY t.groupid) x ON x.groupid = t.groupid
AND x.max_age = t.age
So what if there's 2+ people with the same age for a group? It'd be better to store the birthdate rather than age - you can always calculate the age for presentation.
Try this (assuming Group is synonym for Household)
Select * From Table t
Where Age = (Select Max(Age)
From Table
Where GroupId = t.GroupId)
If there are two or more "oldest" people in some household (They all are the same age and there is noone else older), then this will return all of them, not just one at random.
If this is an issue, then you need to add another subquery to return an arbitrary key value for one person in that set.
Select * From Table t
Where Id =
(Select Max(Id) Fom Table
Where GroupId = t.GroupId
And Age =
(Select(Max(Age) From Table
Where GroupId = t.GroupId))
SELECT GroupID, Name, Age
FROM table
INNER JOIN
(
SELECT GroupID, MAX(Age) AS OLDEST
FROM table
) AS OLDESTPEOPLE
ON
table.GroupID = OLDESTPEOPLE.GroupID
AND
table.Age = OLDESTPEOPLE.OLDEST
SELECT GroupID, Name, Age
FROM table
INNER JOIN
(
SELECT GroupID, MAX(Age) AS OLDEST
FROM table
**GROUP BY GroupID**
) AS OLDESTPEOPLE
ON
table.GroupID = OLDESTPEOPLE.GroupID
AND
table.Age = OLDESTPEOPLE.OLDEST