query from two tables - sql-server-2005

I've 2 tables:
nameTable
userName
userId
classId
marksTable
userId
classId
courseCode
marks
i want to display userId, userName, courseCode, marks of all the students having same classId.
create proc mark__classId
#classId int
as
select marksTable.courseCode, marksTable.userId, marksTable.marks, nameTable.userName
from marksTable, nameTable
where
marksTable.classId = nameTable.classId
but this query gave very vague o/p.
Suppose "name1" with id NAME1 with classId 10 follows courseCode 'C1, C2, C3' with respective marks '80,99,90'
now I want to display all this information when I give input as
exec mark__classId 10

Your select should be more like this, you just need to use your incoming parameters. As well as you should be using a JOIN instead of a CROSS JOIN with a filter
SELECT marksTable.courseCode, marksTable.userId, marksTable.marks, nameTable.userName
FROM marksTable
JOIN nameTable
ON marksTable.classId = nameTable.classId
WHERE marksTable.classId = #classId

Related

SQL query - list of items in one table not in another

I need some help with a SQL query. I have a table of courses and a table that contains user id and course id, denoting courses that user has taken (might not have taken any; no entry in that table for that user id).
I need a query to return the list of courses not taken.
Course Category table
CategoryID
Caegory
Courses table
CourseID
CategoryID
CourseName
...
UserCourse table
UserID
CourseID
you can use not exists
Select *
From Courses c
Where Not Exists (Select 1 From UserCourse uc Where uc.CourseID = c.CourseID)
This will just list the course
select *
from Courses C
Left join CourseCategory cc on
cc.CategoryID = c.CategoryID
where CourseID not in (Select CourseID from UserCourse where UserID = 14)
what i need is for a given user id and course category, what courses within that category have not been taken by this user
(This should have been in the request by the way.)
So:
Select from courses.
Limit to the desired category.
Limit to courses not in the set of courses taken by the user.
The query:
select *
from courses
where categoryid = 123
and courseid not in (select courseid from usercourse where userid = 456);
Another way of writing same query, which will perform faster.
select C.CourseID,C.CategoryID
from Courses C
Left join CourseCategory cc on
cc.CategoryID = c.CategoryID
left join UserCourse uc
on C.CourseID=uc.CourseID
where uc.CourseID is null

Mapping table join query

I have three tables as follows,
student
category
student_category
Student table has the following columns:
studentid, student name, studenttype
Category table has the following tables:
categoryid, categoryname, ..
student_category table has the following columns:
id, studentid, categoryid
Now I have 2 input parameters categoryid and studenttype so now I need to get the all the student details which are associated with respective categoryid and whose student type is studenttype
I tried as follows which is not giving correct result,
SELECT
s.*
FROM
student s
JOIN
student_category sc ON sc.categoryid = 1;
Also I also need to filter student whose studenttype is 'someinput'
I am working on PostgreSQL. Any suggestions please
You should add a where clause and also use the appropiate join condition.
SELECT s.*
FROM student s
JOIN student_category sc ON sc.studentid = s.studentid
where s.studenttype = 'studenttype' --or your desired value
and sc.categoryid = 1

SQL Select entries where none of the entities have a value in a particular column

I have a table of data which has students and their subject results in it. The students will appear multiple times, once for each subject they have a result for.
**tableID,studentID,lastName,firstName,subject,grade**
1,1a,Student1,Name1,English,A
2,1a,Student1,Name1,Maths,A
3,1a,Student1,Name1,Science,A
4,2a,Student2,Name2,English,A
5,2a,Student2,Name2,Maths,B
6,2a,Student2,Name2,Science,A
7,3a,Student3,Name3,English,A
8,3a,Student3,Name3,Maths,A
Using Microsoft Access SQL, how can I select only the students who have received an A for all of their subjects? E.g. In the above table, I only want to select all instances of Student1 and Student3, I don't want Student2 as they have not received all A's.
Get all students with grade A except students with any other grade
SELECT
studentID,lastName,firstName
FROM
(SELECT
studentID,lastName,firstName
FROM
result
WHERE
grade = 'A'
GROUP BY
studentID,lastName,firstName) GradeA
LEFT OUTER JOIN
(SELECT
studentID,lastName,firstName
FROM
result
WHERE
grade <> 'A'
GROUP BY
studentID,lastName,firstName) GradeOther
ON GradeA.studentId = GradeOther.StudentID AND GradeA.LAstName = GradeOther.LastName AND GradeA.FirstName = GradeOther.FirstName
WHERE
GradeOther.StudentID IS NULL
One way is using GROUP BY and HAVING:
select StudentId
from t
group by StudentId
having max(grade) = min(grade) and max(grade) = 'A';
I was able to get the results I want by using a sub-query:
SELECT studentID, lastName, firstName
FROM table
WHERE grade = "A"
AND studentID NOT IN (SELECT studentID FROM table WHERE grade <> "A" GROUP BY studentID)
GROUP BY studentID, lastName, firstName
This seems to exclude all students who received a result other than an A.

Joining Data Between 2 SQL Tables

Okay, I'm not as SQL savvy as I should be, but I'm familiar with how Joins, Unions, etc... work and I just can't come up with a solution for this. I'm trying to get data from two different tables, but the monkey wrench is that the right side table may have more rows than I actually want in my result set. The only criteria I have to join the two tables is an email address. Here's the code:
CREATE TABLE #PPEInfo(StudentEmail nvarchar(128), StudentName nvarchar(128), DevUnits int)
INSERT INTO #PPEInfo (StudentEmail, DevUnits)
SELECT e.StudentEmail AS Email, sum(ck.DevelopmentUnits) AS DevUnits
FROM Enrollments e, CourseKeys ck
WHERE e.CertGenerated = 'true'
AND e.CourseId = ck.CourseId
GROUP BY e.StudentEmail
ORDER BY DevUnits DESC
SELECT p.StudentEmail, p.DevUnits, s.StudentName
FROM #PPEInfo p
RIGHT OUTER JOIN Surveys s
ON p.StudentEmail = s.StudentEmail
ORDER BY DevUnits DESC, StudentName ASC
DROP TABLE #PPEInfo
The problem is that I receive multiple student names because they may not have used the same one when doing their submissions. For instance:
Email Address James R. Salvati
Email Address James Salvati
The only solution that I've come up with is to populate my temp table with the email addresses first and then query the Surveys table for the name using "TOP(1)" to get only one student name. It does work, but it's very CPU intensive, and I'm dealing with a lot of records. Here's the code (although I didn't care about the DevUnits at this point was just trying to come up with something):
CREATE TABLE #PPEInfo(ID int IDENTITY(1,1), StudentEmail nvarchar(128), StudentName nvarchar(128), DevUnits int)
INSERT INTO #PPEInfo (StudentEmail)
SELECT DISTINCT StudentEmail FROM Enrollments
WHERE CertGenerated = 'true'
DECLARE #rowID int
DECLARE #email nvarchar(128)
SET #rowID = (SELECT max(ID) FROM #PPEInfo)
WHILE (#rowID > 0)
BEGIN
SET #email = (SELECT StudentEmail FROM #PPEInfo WHERE ID = #rowID)
UPDATE #PPEInfo
SET StudentName = (SELECT TOP(1) s.StudentName FROM Surveys s
WHERE s.StudentEmail = #email)
WHERE ID = #rowID
SET #rowID = #rowID - 1
END
SELECT * FROM #PPEInfo
ORDER BY DevUnits DESC
DROP TABLE #PPEInfo
I've never had to actually post on one of these boards. I usually find the solution or figure one out, but this one is just beyond my SQL prowess.
Thanks!!!
It depends on how you want to determine which name to select when there are multiple. One posible way is below:
SELECT p.StudentEmail, p.DevUnits, MAX(s.StudentName)
FROM #PPEInfo p
RIGHT OUTER JOIN Surveys s
ON p.StudentEmail = s.StudentEmail
ORDER BY DevUnits DESC, StudentName ASC
GROUP BY p.studentEmail, p.devUnits
Here you are grouping by email and units and grabbing the "MAX" student name.
Also in your first query you should stop using implicit joins.
Correct me if I'm wrong, but I'm pretty sure that you can do this to achieve what you want:
select * from enrollments
inner join coursekeys on
enrollments.studentemail = coursekeys.studentemail
where coursekeys.studentname=(
select top 1 studentname from coursekeys
where studentemail=enrollments.studentemail
);
I don't have access to a SQL Server at the moment, but I've succesfully achieved this on a MySQL server with similar tables to yours.

SQL Multiple Duplicate Row Detection

I'm trying to determine a correct way to isolate rows within a table that have the same values in 2 columns.
There are two tables, one (Name) with the person's names and IDs, and the other one (Nation) with people's IDs and their nations. I join the two tables with inner join, and now the new table columns consist of an ID, first name, last name, and nation. If I want to find pairs of people who have the same last name and are from the same nation, why isn't
select ID, FName, LName, Nation
from (Name inner join Nation on Name.ID = Nation.ID)
group by Name, Nation
having count(Name) > 1 and count(Nation) > 1
working?
I'm aiming for the result to be a table with columns:
ID -------First--------------- Last ---------Nation
where the last names and nations will be identical pairs while first names will be different.
I feel like the group by part isnt appropriate, but is there even an alternate way? Thanks for any help.
If you are using MS SQL Server:
select
*
from
(
select
Name.*,
Nation.Nation,
cnt = count(*) over(partition by LName, Nation)
from Name
join Nation on Nation.ID = Name.ID
) t
where cnt > 1
Try this:
SELECT * FROM (
SELECT Name.ID, Name.FName, Name.LName, Nation.Nation
FROM Name
INNER JOIN Nation ON (Name.ID = Nation.ID)
) a
INNER JOIN (
SELECT Name.ID, Name.FName, Name.LName, Nation.Nation
FROM Name
INNER JOIN Nation ON (Name.ID = Nation.ID)
) b ON (a.LName = b.LName AND a.Nation = b.Nation)
WHERE a.ID < b.ID
As Simon Righarts hinted, something's not right with the design.
Scenario 1)
If a name can have multiple nations, you would have 3 tables implementing an n:m relationship.
CREATE TABLE name (name_id int, name text, ...);
CREATE TABLE nation (nation_id int, nation text, ...);
CREATE TABLE nationality (name_id int references name(name_id)
,nation_id int references nation(nation_id)
... );
Query for the scenario:
SELECT a.name_id, a.fname, a.lname, n.nation
FROM name a
JOIN nationality na USING (name_id)
JOIN nation n USING (nation_id)
JOIN (
SELECT a.lname, na.nation_id
FROM name a
JOIN nationality na USING (name_id)
GROUP BY 1,2
HAVING count(*) > 1) x USING (lname, nation_id)
Scenario 2)
If a name can only have one nation, there would be a column nation_id in the table name:
CREATE TABLE name (name_id int
,name text
,nation_id int references nation(nation_id), ...);
CREATE TABLE nation (nation_id int, nation text, ...);
Query for this scenario:
SELECT a.name_id, a.fname, a.lname, n.nation
FROM name a
JOIN nation n USING (nation_id)
JOIN (
SELECT a.lname, a.nation_id
FROM name a
GROUP BY 1,2
HAVING count(*) > 1) x USING (lname, nation_id);
All multiple occurrences are included here, not just "pairs" - assuming you meant that.
Your actual description doesn't fit either scenario.