SQL Creating an Alias Column For a Nested Select? - sql

Say I have a Person table and a Courses table. In the Person table I have the column PersonName. In the Courses table, let's say I have CourseTitle,PersonName and CourseDifficulty. CourseDifficulty is 1-4 (4 being the hardest). How do I return a list of people from Person and for each person have a column that shows the most difficult class they're taking by CourseTitle.
As far as I know, I'd get the CourseTitle of the most difficult class Brett is taking by doing the following:
SELECT CourseTitle
FROM Courses
WHERE PersonName = 'Brett'
AND CourseDifficulty = (SELECT MAX(CourseDifficulty)
FROM Courses
WHERE PersonName='Brett')
But how do I run that for each person in the Person table? I want the results to be something like
Brett-SQL For Dummies 4
Tim-Quantum Mechanics
Jane-Thermodynamics 2
Sorry for the noobness. Thanks in advance for the help!

you can use the following
SELECT p.name ,p.address, c.courseTitle ,c.courseDifficulty FROM (
SELECT personName, courseTitle, MAX(courseDifficulty) AS courseDifficulty
FROM course
GROUP BY personName
) AS c RIGHT JOIN person AS p ON p.name = c.personName
here am assuming personName is a unique. Otherwise you can use unique id over here instead on person name and add this field in select statement.

Try this:
SELECT c.CourseTitle, c.PersonName, c.CourseDifficulty
FROM Courses c
WHERE c.CourseDifficulty=(SELECT MAX(c2.CourseDifficulty) FROM Courses c2 WHERE c2.PersonName=c.PersonName)

Related

Query to select person on a table that has a class name on another table

I've been at this for a while.
Basically it's a query that needs to identify:
"In which courses do people who only drink one type of beer teach?
(Name of course (s))"
Table 1 : The relation K contains information about courses: their course code (KKOD), course name (NAME), number of points (POINTS) and course abbreviation (NICKNAME).
Table 2: The relationship PB contains information on people's total beer consumption divided into different varieties: the person's name (NAME), Systembolaget's article number (SYSNR) and the number of liters consumed (LITER).
There's more tables but I believe only those two are needed to respond to the question.
First I wanted to write a query that identifies the people who only have drunken one type of beer.
select * from pb group by namn having count(*)=1;
Then I tried to write a query combining the above query to list the courses but here's where nothing happens or if I do some variations, all of the courses will list, not just the ones I need.
Try 1: select namn from pb group by namn having count(*)=1 where exists(select knamn from K where pb.namn = k.knamn);
Try 2: select knamn from k where exists(select namn from pb by group by namn having count(*)=1);
Doesn't work, any recommendations?
Thank you
The description of the tables seem to be lacking an ability to join them. Let's just assume you have a person_id or name in both tables.
This is the question:
"In which courses do people who only drink one type of beer teach? (Name of course (s))"
You can use a CTE to first obtain the names of people who drink only one type of beer, and use in a query such as this:
with beer_types as
(
select person_name
from beers
group by person_name
having count(distinct beer_type) = 1
)
select c.person_name, c.course_code
from courses c
join beer_types bt
on c.person_name = bt.person_name
DB-Fiddle found here.

Find potential duplicate names in database

I have two tables in a SQL Server Database:
Table: People
Columns: ID, FirstName, LastName
Table: StandardNames
Columns: Nickname, StandardName
Sample Nicknames would be Rick, Rich, Richie when StandardName is Richard.
I would like to find duplicate contacts in my People table but replace any of the nicknames with the standard name. IE: sometimes I have Rich Smith other times it is Richard Smith in the People table. Is this possible? I realize it might be multiple joins to the same table but can't figure out how to start.
Firstly, you need to determine how many duplicates you have in your People table...
SELECT p.FirstName, COUNT(*)
FROM People AS p
INNER JOIN StandardNames AS sn
ON CHARINDEX(sn.Nickname, p.FirstName) > 0 OR
CHARINDEX(sn.Nickname, p.LastName) > 0
GROUP BY p.FirstName
HAVING COUNT(*) > 1
That's just to get an idea of what data you're trying to find in relation to the Nicknames that may possibly exist inside (as a wildcard word search) the Firstname and Lastname columns.
If you are happy with the items found then expand on the query to update the values.
Let's say you wanted to change the Firstname to be the Standardname...
UPDATE p2
SET p2.FirstName = p2.Standardname
FROM
(SELECT p.ID, sn.StandardName
FROM People AS p
INNER JOIN StandardNames AS sn
ON CHARINDEX(sn.Nickname, p.FirstName) > 0 OR
CHARINDEX(sn.Nickname, p.LastName) > 0) AS a
INNER JOIN People AS p2 ON p2.ID = a.ID
So this will obviously find all the People IDs that have a match based on the query above, and it will update the People table by replacing the FirstName with the StandardName.
However, there are issues with this due to the limitation of your question.
the StandardNames table should have its own ID field. All tables should have an ID column as its primary table. That's just my view.
this is only going to work for data it matches using the CHARINDEX() function. What you really need is something to find based on a "sound" or similarity to the nicknames. Check out the SOUNDEX() function and apply your logic from there.
And this is assuming your IDs above are unique!
Good luck
You could standardize the names by joining, and count the number of occurrences. Extracting the ID is a bit fiddly, but also quite possible. I'd suggest the following - use a case expression to find the contact with the standard name, and if you don't have one, just take the id of the first duplicate:
SELECT COALESCE(MIN(CASE FirstName WHEN StandardName THEN id END), MIN(id)),
StandardName,
LastName,
COUNT(*)
FROM People p
LEFT JOIN StandardNames s ON FirstName = Nickname AND
GROUP BY StandardName, LastName

SQL query to select records that have one value in a column but missing another value

I have a database that has two tables. One holds the name of the classes a student can take (class_id, class_desc) and the other has the students information (id, fname, lname, class_id). I join the tables to get a roster of who is taking what class by joining on the class_id. How do I go about getting a roster of students that are taking class 'cl_2055' but not taking class 'cl_6910'?
You really need to change your schema if you can. You should have three tables. Student, Class and StudentClass, (StudentClass contains a pointer to each of the other tables.
But if you insist on using the schema you have...
SELECT
*
FROM
students
WHERE
class_id = 'cl_2055'
AND id NOT IN (SELECT id FROM students where class_id = 'cl_6910')
This assumes the id is not unique, and you are using ID to represent students. If you are using ID to represent records, then you will need the second approach:
SELECT
*
FROM
students students_in_2055
WHERE
class_id = 'cl_2055'
AND NOT EXISTS (
SELECT 1
FROM students students_in_6910
WHERE students_in_6910.class_id = 'cl_6910'
AND students_in_2055.fname = students_in_6910.fname
AND students_in_2055.lname = students_in_6910.lname
)
I like to use aggregation for this purpose
select si.fname, si.lname
from studentinformation si
where ci.classid in ('cl_2055', 'cl_6910')
group by si.fname, si.lname
having min(ci.classid) = 'cl_2055' and max(ci.classid) = 'cl_2055';
First, this assumes that the class identifiers are the ids and not the description (seems logical to me). If they are the descriptions, then you need to join in the class information.
How does this work? The where clause filters down to students who might be in both classes. The group by aggregates to a single row per student. And the having keeps students who are only in "cl_055".

Join a SQL resultset based on common email address

I have one table that contains both students and parents records. There is a common field (email address) in both parent and student records that match the records (parents and students have the same email address).
I want my query to find the common email addresses and return each
student record but it must also include a field (Mifare) from the
parents record.
So I have tried to join and where clauses but i am getting crazy results. I was also thinking of using the with clause.
Expected result is
The basic script is:
Select extid, first_name, last_name, commonemail, designation,mifare
from students
Please assist with a basic coding - no procedures etc...just simple help for a newbie!
Thank you all!
Here is the solution for your problem:
SELECT stud.ExtId,
stud.FirstName,
stud.LastName,
stud.CommonEmail,
stud.Designation,
stud.Mifare,
prnt.Mifare
FROM Students AS stud
INNER JOIN Students AS prnt
ON stud.CommonEmail = prnt.CommonEmail
AND stud.Designation = 'Student'
AND prnt.Designation = 'Parent'
You can also follow the link to the demo:
http://sqlfiddle.com/#!9/5b790b/1
Select s.*
p.mifare
from students s
left join students p on p.commonemail=s.commonemail and p.Designation='Parent'
Try using the following Sub query
Select *,
(Select Mifare from students b where b.Designation = 'Parent' and b.commonemail = a.commonemail) as ParentMifare
from students a
I am not sure you can try this way join both the tables with email select only the designation student only.
Select
st.extid,
st.first_name,
st.last_name,
st.commonemail,
st.designation,
st. mifare
pr.parentmifare
from students st inner join students pr on st.commonemail=pr.commonemail
where pr.designation='student' and st.designation='parent'

SQL finding course name from course code

I have 2 tables, students and courses. In the students table each student has a course code and in the courses table I have course codes with their names.
How can I return the course name when running the query?
So for example if I run a basic SELECT * FROM Students it says "Jimmy | Computing" instead of "Jimmy | 12390814"
JOIN both tables. Try something like this,
SELECT a.*, b.courseName
FROM students a
INNER JOIN courses b
ON a.courseCode = b.courseCode
-- WHERE ....