Condition SQL Join - sql

We have a table of users where most have a school number attached. I've then used an Inner Join to join the school's table to get the name of the school. Some users don't have a school number so there is a NULL value - which means that none of their data is appearing. Is there a way I can do a conditional join dependent on the schoolid field?
Users Table:
Name | Schoolid
-----|---------
John | 27
Fred | 49
Sam | NULL
School Table:
Schoolid | Schoolname
----------|-----------
27 | John's School
49 | Fred's School
When the tables are Joined on the Schoolid the results are
Name | Schoolname
-----|-----------
John | John's School
Fred | Fred's School
Ideally I would like the results to look like this:
Name | Schoolname
-----|-----------
John | John's School
Fred | Fred's School
Sam | NULL
Can anybody help? Is it something simple and I'm just being an idiot?
Thanks

You're looking for an outer join.
E.g.
select * from Users left outer join School on Users.Schoolid = School.Schoolid
Microsoft has an article with some examples that may make it more clear, even if you're using a different SQL dialect.

SELECT *
FROM Users u
LEFT OUTER JOIN School s ON u.Schoolid = s.Schoolid
Or even.
SELECT *
FROM Users u
FULL OUTER JOIN School s ON u.Schoolid = s.Schoolid

Related

SQLite: Splitting multiple selects into different columns

I need to achieve the following looking output in SQL:
chair | Secretary | Year
------------------------
Matt | Susan | 2006
Susan | Joe | 2005
From a database with tables Members and Leaders. Table Members looks as follows:
Name | num
-------------
Matt | 123
Susan | 456
Joe | 789
Table Leaders looks as follows:
Year | Chair | Secretary
-------------------
2006 | 123 | 456
2005 | 456 | 789
So far I've come up with something like this:
SELECT * FROM
(SELECT m.name FROM Members M, Leaders L
WHERE M.num = L.secretary
UNION ALL
SELECT m.name FROM MEMBER M, Leaders L WHERE M.num = L.chair
UNION ALL
SELECT L.year from Leaders L);
However, this selects all of the wanted parameters as one column. My question is: How do I make it so that the names in particular are split into Chair and Secretary columns when they are derived from the same table?
In my opinion you could build your query in this way:
SELECT l.year, m1.Name, m2.Name
FROM leaders l
INNER JOIN members m1 ON l.chair = m1.num
INNER JOIN members m2 ON l.secretary = m2.num
You can find a test here
You have to use ALIAS, which can be defined with AS keyword (that can be omitted). ALIAS can be used for tables and for columns, like in the example below:
SELECT
ChairMembers.Name AS Chair,
SecretaryMembers.Name AS Secretary,
Year
FROM
Leaders
INNER JOIN
Members AS ChairMembers
ON
Leaders.Chair = ChairMembers.num
INNER JOIN
Members AS SecretaryMembers
ON
Leaders.Secretary = SecretaryMembers.num
For more information you can read this documentation.

How to build an SQL query that directs two different columns to the same reference column

I am getting a bit confused with this basic SQL question, I was hoping you could give me a hint about what am I doing wrong:
I have a main table with different players:
id | name
----+-----
1 | John
2 | Paul
3 | Robert
And another table that stores their matches
date | player_home | player_away
----------+---------------+-------------
2012-03-21| 1 | 2
2012-04-10| 2 | 3
I am trying to build a query that outputs the names of both players for a given date, but the name of the same player is being repeated in both fields:
This retrieves nothing:
SELECT date, player_home, name, player_away, name
FROM games, players
WHERE date = (DATE '2012-03-21')
AND games.player_home = players.id
AND games.player_away = players.id;
And if I remove the second AND, it retrieves the same name (John) for both players:
date | player_home | name | player_away | name
----------+---------------+---------+----------------+-------
2012-03-21| 1 | John | 2 | John
When the name in the second "name" field should be "Paul".
What is the right way to build this query?
Thanks in advance
You need to join the players table twice and use different alias names for the tables
SELECT g.date, p1.name as home_name, p2.name as away_name
FROM games g
JOIN players p1 ON g.player_home = p1.id
JOIN players p2 ON g.player_away = p2.id
WHERE g.date = (DATE '2012-03-21')
SELECT date, player_home, players_home.name, player_away, player_away.name
FROM games
left outer join players players_home on player_home=players.id
left outer join players players_away on player_away=players.id
WHERE date = (DATE '2012-03-21') ;

selecting rows the id's of which appear in a column of another table

I can't quite get my head around a SQL query because it is not my forté. I'm trying to select the names of rows in an employees table the id's of which appear in a column salesPersonId of another table, accounts. That is, any employee name which is represented in the accounts table.
ACCOUNT
+----+---------------+
| id | salesPersonID |
+----+---------------+
| 0 | 1020 |
+----+---------------+
| 1 | 1020 |
+----+---------------+
| 2 | 1009 |
+----+---------------+
EMPLOYEE
+------+---------------+
| id | firstName |
+------+---------------+
| 1009 | BILL | <-select his name
+------+---------------+
| 1020 | KATE | <-select her name
+------+---------------+
| 1025 | NEIL | <-not this guy
+------+---------------+
Since Neil hasn't got any presence in account.salesPersonID, I'd like to select the other two besides him. I'm not getting very far with it though, and looking for some input.
SELECT * FROM employee e
LEFT JOIN account a
ON a.salesPersonID = e.id
WHERE (SELECT COUNT(salesPersonID) FROM account) > 0
does not work. I wonder how I could select these employee names that are present in salesPersonID. Thank you.
Try this:
SELECT Distinct e.firstName
FROM employee e
JOIN account a ON a.salesPersonID = e.id
The JOIN will take care of the filtering to make sure that you are only returning the records that exist in both tables.
Distinct will make sure that you are only getting each firstName value one time. You can also accomplish this by Grouping by employee.Id or employee.firstName (grouping by Id is the better strategy if you want to return one row for each unique employee, even if they have the same first name, grouping on firstName or using distinct is for when you just want one of each unique name, even if the name is used by more than one employee)
u can have the query like this....
select e.firstname from employees1 e left join account a on(e.id=a.salespersonid)
where e.id= a.salespersonid
group by e.firstname
result:
firstname
bill
kate

SELECT a subset of records from Table A that match two columns in table B

I have a list of users in a database table called Users (SQL Server 2008 R2). In addition to the user's UserName, there are two fields that classify the user - for simplicity we'll say Department and JobTitle.
| UserName | Department | JobTitle |
------------------------------------------
| Joe | IT | SysAdmin |
| Jim | IT | DBA |
| Jeff | Sales | SalesMgr |
| Mack | Sales | Rep |
I also have a table, ActiveJobs, that lists certain combinations of Department and JobTitle that I actually care about.
| Department | JobTitle |
-----------------------------
| IT | SysAdmin |
| Sales | SalesMgr |
| Sales | Rep |
I want to select each of the records from Users that matches the combination of Department / JobTitle in ActiveJobs. I thought this query would do it:
SELECT Users.*
FROM Users
INNER JOIN ActiveJobs DEP
ON Users.Department = DEP.Department
INNER JOIN ActiveJobs JOB
ON Users.JobTitle = JOB.JobTitle
But that returns the same User record more than once in many cases (which I think is caused by the duplicates in the Department column - but I don't really understand why). For the example above, I'm getting (Joe, Joe, Jim, Mack) even though I was hoping to just get (Joe, Jim, Mack).
What query would get the subset of User records that has a matching combination of Department and JobTitle in Active Jobs?
Put an "AND" in your join clause instead of joining twice.
SELECT Users.*
FROM Users
INNER JOIN ActiveJobs DEP
ON Users.Department = DEP.Department AND Users.JobTitle = DEP.JobTitle
Seems like one join on two attributes would work, rather than two joins on one attribute each. Can you JOIN ON ... AND ... ? (Away from computer)

How to join mysql tables

I've an old table like this:
user> id | name | address | comments
And now I've to create an "alias" table to allow some users to have an alias name for some reasons. I've created a new table 'user_alias' like this:
user_alias> name | user
But now I have a problem due my poor SQL level... How to join both tables to generate something like this:
1 | my_name | my_address | my_comments
1 | my_alias | my_address | my_comments
2 | other_name | other_address | other_comments
I mean, I want to make a "SELECT..." query that returns in the same format as the "user" table ALL users and ALL alias.. Something like this:
SELECT user.* FROM user LEFT JOIN user_alias ON `user`=`id`
but it doesn't work for me..
I think you need something like this:
SELECT user.*
FROM user
LEFT JOIN user_alias
ON user.name=user_alias.name
Your original query was not specific enough in the join condition.
Something like
SELECT user.name, user.address, user.comment FROM user
UNION ALL
SELECT user_alias.alias, user.address, user.comment
FROM user INNER JOIN user_alias on user.name = user_alias.name
ORDER BY name
will get you close to what you want.
You need to UNION two SELECTs together because the LEFT JOIN solution proposed by others will include only one row in the result set for users with aliases, not two as specified in your question.
But you should make the common column joining user and alias the id column, not the name column.
SELECT user.* FROM user LEFT JOIN user_alias ON user.name = user_alias.name
First of all - the query you want to build is not trivial, because you are trying to get some results spanned across more than one row. So I will offer you a proper solution in a fashion like it should be (read: in a way a database developer will do this :-).
First, you should modify your user_alias table so that it will contain id column but not the name. It is not good idea to join your tables using the name field. The reason for this is that there could be two Sarah Connors.
Then, you can get results from both tables using this query:
SELECT user.*, user_alias.*
FROM user LEFT JOIN user_alias
ON user.id=user_alias.id
This way you will get your results in such format:
id | name | address | comments | user
-------------------------------------------------------------
1 | Sarah Connor | Planet Earth | Nice woman | sarah_connor
2 | Sarah Connor | USA, NY | Mean woman | sarah_c
3 | John Connor | USA, NY | n00b | john123
In the situations when there are two or more records in user_alias table for the same person (equal id's), you will get something like this:
id | name | address | comments | user
-------------------------------------------------------------
4 | Bill Clinton | White House | President | bill
4 | Bill Clinton | White House | President | monica