sql query to count and display full name - sql

So I am very confused by this query to display teachers' full name. I have used teacher_name ||' '|| teacher_lastname, but when I try to do so for the students, something happens. I am trying to get number of times a teacher had an appointment with a student and display teacher fullname and students full name. Below is my query :
select d.teacher_id ||' '|| d.teacher_lastname as Teacher, count (distinct c.student_id)
from teacher d inner join class t on t.teacher_id=d.teacher_id
inner join classRoom tp on tp.dest_id=t.dest_id
inner join classFl ta on tp.dest_id=ta.dest_id
inner join students c on c.student_id=ta.student_id
group by d.teacher_id,d.teacher_lastname
This is the output, but when I add
select d.teacher_id ||' '|| d.teacher_lastname as Teacher,
c.student_name||' '||c.student_lastname as Student,
count (distinct c.student_id)
and also add it to the group by d.teacher_id,d.teacher_lastname,c.customer_name,c.customer_lastname
it gives the following result
What is wrong? How can I fix it to have the same nr of counts for each teacher?
I am using oracle sql developer

I think you need to remove the DISTINCT from inside the COUNT. You say you want "nr of times a teacher had an appointment with a student" which I interpret to mean that if teacher T saw student S 9 times you want:
T S 9
If you keep DISTINCT, then grouping on student name and counting the number of unique student IDs will only ever produce a 1 unless two students have identical names. In essence then, by keeping the DISTINCT you are counting "the number of different students with name X that that teacher met with" and mostly this is 1 because "1 unique student named Hana Baker met with xxxx yyyy", "1 unique student with name Dream Kenise met with xxxx yyyy" ....
If you do have students with the same name but a different ID, then you should add student ID to the GROUP BY to provide distinction between the two students. You don't have to add it to the SELECT, but you'll struggle to tell them apart if you do. If you have two students both called S, but one has ID 1 (and he saw T 5 times) and the other has ID 2 (and she saw T 4 times) you'll get a result of:
T S 5
T S 4
You might want to add other columns to your select to better tell the difference between them
In your first query, using DISTINCT meant "the number of different students that sought a meeting with the teacher". Omitting DISTINCT in that query would have counted "the number of times the teacher had a meeting with any student"

Related

SQL : Getting count of a column and then multiplying it with a column from another table

I have three tables in my database,
Students-has student id,
Instructors which has instructor id, course name and hourly pay.
Enrollment table which has student id, course name, instructor.
I need to write a query to get the max amount of money paid to an instructor. Somethings to consider
A student can enroll into multiple courses
An instructor can teach multiple courses (Instructor is paid the same for each course)
Multiple instructors can teach the same course.
I came up with the required tables to get the entries first.
select hourlyPay, ins_id, stu_id from Instructors, Enrollment where Enrollment.ins_id = Instructors.Instr_id group by hourlyPay,ins_ID,stu_id
This gives me the output:
My end goal is to multiply the hourly pay with the student count and get the maximum, Could somebody please help me do it? I want the student count per instructor multiplied with the hourly pay.
Since I don't know the data and complete requirement. You can try something below:
(This top 1 works in SQL Server). I think in Orcle you need try FETCH FIRST number ROWS ONLY;)
select top 1 ins_id,sum(hourlyPay) Pay
from(
select hourlyPay
, ins_id
, stu_id
from Instructors
Join Enrollment ON Enrollment.ins_id = Instructors.Instr_id
group by hourlyPay,ins_ID,stu_id
) a
group by ins_id
order by 2 desc

SQL question: how to find rows that share all of the same rows in a composite table?

I'm working on my SQL project using the Oracle database for class, and I'm asked a question that I see far too often.
You have three tables:
STUDENT: SNO, SNAME
CLASS: CNO, CNAME
ATTENDANCE: SNO, CNO, Grade
The question I keep finding is of a similar type: Find the names of the students that attend in all of the classes that "John" (or anyone else) attends.
John attends three classes, so I have to find the students that also attend those three classes (could be more, but those three must be there). However, I won't always know how many classes John (or whoever) attends, so it can't be hardcoded like that.
SELECT jclass.CNO
FROM attendance jclass
INNER JOIN student on jclass.SNO = student.SNO
WHERE student.SNAME = 'John';
This gets me the classes that John attends. I tried to add the identifier for the other students:
SELECT student.SNAME
FROM student
INNER JOIN attendance on student.SNO = attendance.SNO
INNER JOIN class on attendance.CNO = class.CNO
WHERE student.SNAME <> 'John'
AND class.CNO IN (SELECT jclass.CNO
FROM attendance jclass
INNER JOIN student on jclass.SNO = student.SNO
WHERE student.SNAME = 'John');
However, this only gets me the students that appear in at least one of John's classes, rather than all of them. I can see why it's doing this, but I'm not sure how to fix it. It's the one big struggle I'm having with SQL.
Here is one way - assuming SNO is primary key in the first table, CNO is primary key in the second table, and (SNO, CNO) is (composite) primary key in the third table, and that the input student is given by a unique identifier (first name is distinctly NOT a unique identifier, so the problem stated in terms of giving "John" as the input makes no sense). Here I assume the "special" student is identified by SNO = 1001; you can make 1001 into a variable, or change it to a subquery that selects a (unique!!) SNO based on some other inputs.
I didn't try to make the query as efficient as possible, or use features you most likely haven't seen in your class. Rather, I tried to make it as elementary and as readable as possible.
select sno
from attendance
where cno in (select cno from attendance where sno = 1001)
group by sno
having count(*) = (select count(*) from attendance where sno = 1001)
;
The strategy is simple: the subquery in the in condition finds the classes attended by the "special" student, then from the attendance table we select only rows for those classes. Group by student, and count. Keep only the students for whom the count is equal to the total count for the "special" student. Note the last condition is about groups, not about input rows, so it belongs in the having clause.

Access flag record when match found in table 2 (one-to-many relationship)

I have an educational db with a tbl_Students and tblStudentPrograms. The tblStudentPrograms has one record per student and program (ProgramID) per year (YearID.
I need to find out how many students participated in ProgramID=2 EVER. So, I need the DISTINCT subset of students who have participated in the program for any YearID.
(Of course, this will be complicated further by trying to find other records in other tables such as StudentAdvising as well , but this will be a good start.)
Thank you!
SELECT DISTINCT count(studentID) FROM tblStudentPrograms WHERE ProgramID = 2
Assuming you want a distinct count of students (excluding those where the same student may have taken a program twice...
SELECT count(distinct StudentID)
FROM tblStudentPRograms
WHERE ProgramID = 2
Assuming you want a distinct count of students (excluding those where the same student may have taken a program twice...
SELECT count(distinct StudentID)
FROM tblStudentPRograms
WHERE ProgramID = 2
though I'm not positive access supports a distinct w/in a count like other RDBMS do...
so you may have to do:
SQL : how can i count distinct record in MS ACCESS
SELECT count(BStudentID) as DistinctStudentsInProgram
FROM (select distinct studentID, ProgramID from tblStudentPrograms) B
WHERE B.ProgramID = 2

SQL query number of students per school

I have a table of students and schools. How do I select the total students per school?
I'm sure this is a very simple query, however I'm not sure how to proceed on from this:
SELECT tblSchools.name
FROM tblStudentDetails
INNER JOIN tblSchools
ON tblStudentDetails.schoolId = tblSchools.id
Group by the school and use count() to count the students
SELECT s.name, count(d.id) as students_count
FROM tblSchools s
INNER JOIN tblStudentDetails d ON d.schoolId = s.id
GROUP BY s.name
I want to add on to the accepted answer as well. Working for a school district and continuously having to pull counts of students there are a few additional things to keep in mind. What students are you looking for?
Do you want active students, inactive students, or active and inactive students.
Do you want to include students that have been no showed (were going to come to your school, but ended up not coming for even a day, this is recorded in most student information systems.
Is the student attending multiple schools, in which case you want to exclude them from counting in their second or third school.
I've built the script with the idea of a normalized school district database, where things are broken out by school year, and enrollment.
Often a basic script for me looks a little like this.
SELECT s.SCHOOL_NAME, COUNT(stu.STUDENT_GU) AS STUDENT_COUNT
FROM STUDENT stu
JOIN STUDENT_YEAR sy ON sy.STUDENT_ID = stu.STUDENT_ID
JOIN SCHOOL_YEAR scy ON scy.SCHOOL_YEAR_ID = sy.SCHOOL_YEAR_ID
JOIN SCHOOL s ON s.SCHOOL_ID = scy.SCHOOL_ID
JOIN YEAR y ON y.YEAR_ID = sy.YEAR_ID
WHERE y.SCHOOL_YEAR = 2017
AND (sy.CONCURRENT IS NULL OR sy.CONCURRENT OR != 'Not Concurrent')
AND sy.ENTER_DATE IS NOT NULL
AND sy.STATUS IS NULL
GROUP BY s.SCHOOL_NAME
Because each school year is a new year, students, and schools usually have a table for the basic data that doesn't change. But also tables that are school year specific. In my example STUDENT_YEAR and SCHOOL_YEAR is where we get into the specifics regarding which kids we are actually getting, and where they currently are. I utilize the YEAR table to identify which school year I want to look at.
The STUDENT_YEAR table is where we store the students concurrency flag, enter date, and so within that table I can use in the WHERE clause a way to filter out Inactive Students, Concurrent Students, and ensure each student is counted only once.
If those year values aren't included, at least in my database, I would get all students ever enrolled for every year we've got stored.

SQL Server query to know if an id in a column equals to other in another column

I’ve been hours trying to build this query and I need your help so I can make it.
This is table Students (made out of inner joins):
SpecialtyChosenID StudentID Subject SubjectSpecialtyID
5ABFB416-8137 15 Math A1EBF3CB-E899
5ABFB416-8137 15 English A1EBF3CB-E899
The info in it means that a student with id no. 15 has chosen an specialty with id 5ABFB416-8137
The two subjects he has passed (Math and English) belong to a specialty with id A1EBF3CB-E899
What would be the query to know if the passed subjects belong to the specialty chosen by the student??
Counting the number of subjects with the same SubjectSpecialtyID as SpecialtyChosenID and vice versa could do.
Thanks a lot
You can do a self join. This finds the number of subjects taken by the student that match the student's chosen specialities.
SELECT l.SpecialtyChosenID, l.StudentID, Count(Distinct r.Subject) FROM Students l
LEFT JOIN Students r ON (l.StudentID=r.StudentID AND l.SpecialityChosenID=r.SubjectSpecialityID)
GROUP BY l.SpecialtyChosenID, l.StudentID
However, this is quite inefficient using the table structure given. If you have a table listing students with their specialities, and another with subjects and specialities, and a third relating students with subjects, it would be better to build this query from the base data, rather than from the derived data.
SELECT * FROM Students WHERE SpecialtyChosenID = SubjectSpecialtyID
If you only need the list of matching subjects and you have the SpecialtyChosenID you can do something like
SELECT * FROM Students
WHERE SubjectSpecialtyID = SpecialityChosenID
CASE WHEN SpecialtyChosenID = SubjectSpecialtyID THEN 1 ELSE 0 END AS specialty