SQL select multiple rows and order them by id - sql

I got a Student with a few parameters, like Id, Name, etc.
Now I got another one table called ACCOUNTS, they have an id and a name...
the relation between these two is OneToMany (one student can have more accounts)
and i need a SQL query to show all accounts for the student...here is what i have, but it's not working...
"Select distinct s from Student s left join fetch s.accounts where s.id=:studId"
I should say that the Student has a field called accounts
And at the end of the query, i placed already ORDER BY and then the following code didn't work:
s.accounts.id
account.id
student.account.id
So...long story short...the query above, shows the accounts of the specific student...now i just need to order them by the id of the accounts
Any suggestions?

As OP confirmed adding it as answer.
select distinct s.id, s.name, a.id
from students s left outer join accounts a on s.id = a.id
order by s.id, a.id;

one student can have more accounts
So it's two tables:
student (id, name, ...)
accounts (id, student_id, ...)
I should say that the Student has a field called accounts
That makes no sense. By this you would store one account per student and several students could share one account. So I stick to the first statement that one student can have several accounts and the tables look more or less like I've shown above.
You want to see accounts for one student. So you select from accounts where the student ID matches:
select * from accounts where student_id = :studId order by account.id;
If you want to show student data along, you'd join the tables instead:
select *
from student s
left join accounts a on a.student_id = s.id
where s.id = :studId
order by a.id;

Related

outer join with not in and for each in sql

This one has only one table with three columns student, lect and score. for each lecture I need to find the students who have not got any score.
I have written the below query which uses outer joins, but it can do so only for one lect at a time.
Eg: see below I passed 'L02'
How do I get this working for all the lect values as in (L01,L02,L03...etc)
select distinct * from
(
select distinct Student from import1
where lect ='L02'
)i1
right outer join
(select distinct Student from import1) i2
on i1.Student=i2.Student
where i1.Student is null
output of above is
This works for L02. But, how do I modify above to include for all lect values without hardcoding the values of lect?
Sample data from table:
Need a dataset of all possible student/lecture pairs. If the one table contains all the students and lectures that need to be considered, this dataset can be built with:
SELECT Student, Lect FROM (SELECT DISTINCT Student FROM import1) AS S, (SELECT DISTINCT Lect FROM import1) AS L
Otherwise, need a table of all students and a table of all lectures then query:
SELECT Student, Lect FROM Students, Lectures
Now join that query to the scores table with compound link on both identifier fields and use appropriate filter criteria.
SELECT Query1.Student, Query1.Lect, import1.Score
FROM Query1 LEFT JOIN import1
ON (Query1.Lect = import1.Lect) AND (Query1.Student = import1.Student)
WHERE Score Is Null;
Tested with an Access database.

Microsoft SQL Server : max date joining two tables

I am attempting to join two tables while pulling the max date from one.
I have a student table and a communication table. Each student is unique in the student table and has many communication entries.
I would like to create a SQL script that pulls each student's ID, name, latest communication date, and the communication message for that date.
I am able to pull the latest date for each student using max(comm_date) and group by, but things get messy (many duplications) when pulling the corresponding communication message.
Table: Student
studentid, name
Table: Communications
studentid, comm_date, comm_msg
Result:
student.studentid, student.name, communications.comm_date, communications.comm_msg
How can I pull the corresponding communication message given max(comm_date)?
This should get you what you need. I don't know if there's a performance hit doing this via nested subquery, but I like the clean syntax of this:
SELECT
s.studentid,
s.name,
LastCommDate = MAX(c.comm_date),
LastCommMessage = (SELECT comm_msg FROM Communications WHERE studentid = s.studentid AND comm_date = MAX(c.comm_date))
FROM Student AS s
INNER JOIN Communications AS c
ON s.studentid = c.studentid
GROUP BY s.studentid, s.name
This should get what you need...
select
s.studentid,
s.name,
c2.comm_date,
c2.comm_msg
from
Student s
LEFT JOIN
( select
c1.studentid,
max( c1.comm_Date ) as MaxDate
from
Communications c1
group by
c1.studentid ) PreMax
on s.studentid = PreMax.StudentID
LEFT JOIN Communications c2
on PreMax.StudentID = c2.StudentID
AND PreMax.MaxDate = c2.comm_Dat
Additionally, I would suggest adding a column to your student table for most recent communication date (or even an ID if communications has an auto-increment column such as multiple entries on the same day). Then, via an insert trigger to the communications table, you update the student table with that newest date (or communication ID). Then you never need to keep requerying the MAX() and re-joining multiple times as this one does.

Where SQL column value not found in other column

I've read similar questions and I think I am doing it correct, but I just wanted to make sure my SQL is correct. (Still new to SQL)
I have 2 different tables
Students
id, name, address
Staff
id, name, address
I need to find the total number of students (who are not also staff)
SO I have the following SQL
create view nstudents as
select students.id
from students
LEFT JOIN staff ON staff.id = students.id;
Then I run the count(*) on the view.
Can someone confirm my SQL is correct or is there better way to do it?
Your LEFT JOIN doesn't eliminate students who are also staff, but it could be useful in achieving your goal. LEFT JOIN provides you with all results from the left table and matching results from the right table, or NULL results if the right table doesn't have a match. If you do this:
select count(*)
from students
LEFT JOIN staff ON staff.id = students.id
WHERE staff.id IS NULL;
I expect you'll get what you're looking for.
You might find it more natural to do something like this:
create view nstudents as
select s.id
from students s
where not exists (select 1 from staff st where st.id = s.id) ;
This should have the same performance as the left join.

SQL count after joining two tables

I am newbie to SQL, I would like to come up with a count, assume this example with 2 tables:
School(schoolID, name,....)
Student(StudentID, SchoolID, ...)
I tried:
SELECT COUNT(studentID)
FROM School s, Student t
WHERE s.schooldID = t.schoolID
How can I get a count of all students across all schools?
Since you have the school ID in the student table, it doesn't appear to me that you need to join to school at all. Just select a count from the student table and group by schoolID:
SELECT schoolID, COUNT(*) AS numStudents
FROM student
GROUP BY schoolID;
The only reason you'd need to join to School is if you want other information, such as school name and so on. If you just want the school id and number of students, the above will work.
To complete that last thought, possibly irrelevant to your question. If you did want school name, you just do an inner join and put school.name in your select statement, along with the count from the student table and group by school ID still:
SELECT s.name, st.COUNT(*) AS numStudents
FROM student st
JOIN school s ON s.id = st.schoolID
GROUP BY s.id;
If you want to get the count per school, you need a group by. Also, usually we prefer ANSI style joins, since in fact all database systems support them nowadays and they easier to read and maintain:
select count(t.studentID)
from Student t
join School s /* added join for your convenience, not necessary here */
on s.schooldID = t.schooldID
group
by t.schoolID

where not exists clause sql

So I am trying to list students that are in at least one class but are not part of a group. My code is showing up 0 results but there should be two. Something is wrong with my where clause. I can get it to show students taking one or more classes, just cant get it to show the ones that are also not part of any group. There is something wrong with my where clause. I have 3 tables that are related. Student which holds student name and ID, Member of, which holds student ID and group ID, and studentgroup which holds group ID.
Code:
select student.lastname
from student inner join enrolled on enrolled.studentid = student.sid
where not exists(
select *
from studentgroup inner join memberof on memberof.groupid = studentgroup.gid
)
You don't have any condition that states how the student would be associated with the student group. So, the EXISTS always returns true, but you want to see the rows where the EXISTS returns false.
You can add the WHERE in the sub query to associate the student with the group.
SELECT student.lastname
FROM student INNER JOIN enrolled ON enrolled.studentid = student.sid
WHERE NOT exists(
SELECT *
FROM studentgroup INNER JOIN memberof ON memberof.groupid = studentgroup.gid
WHERE student.sid = memberof.studentid
)
what if you changed the where clause from where not exists to where not in? something like
where student.id not in (select distinct student_id from member_of)