SQL combining two tables without duplication - sql

I want to combine two tables based on a column. Here's an example:
These are my two tables:
Table1 Table2
Person | salary Person | Age
Tim | 22.50 Larry | 32
Tony | 49.00 Tim | 22
John | 32.67 Tony | 44
Kim | 23.42 John | 31
And my resulting table should be:
Person | salary | Age
Larry | | 32
Tim | 22.50 | 22
Tony | 49.00 | 44
John | 32.67 | 31
Kim | 23.42 |
Everyone is added to the resulting table only once even if they don't have a value for both salary and age
Thanks in advance!

Since you have tagged this as MS-ACCESS I will provide SQL code for MS ACCESS
Because Microsoft does not have the capability to do a FULL OUTER JOIN, you have to think of a clever way to use existing SQL commands to create a FULL OUTER JOIN. The following code should do the trick using your tables above:
SELECT Table1.Person, Salary, Age
FROM Table1 INNER JOIN Table2 ON Table1.Person = Table2.Person
UNION ALL
SELECT Table1.Person, Salary, Age
FROM Table1 LEFT JOIN Table2 ON Table1.Person = Table2.Person
WHERE Table2.Person Is Null
UNION ALL
SELECT Table2.Person, Salary, Age
FROM Table1 RIGHT JOIN Table2 ON Table1.Person = Table2.Person
WHERE Table1.Person Is Null

This could have been done by full outer join but since you are using ms access you will have to use union all in the below manner.
Try this out and let me know in case you face any difficulties.
SELECT * FROM table1 t1
LEFT JOIN
table2 t2
ON t1.person = t2.person
UNION all
SELECT * FROM table1 t1
RIGHT JOIN
table2 t2
ON t1.person = t2.person

I don't see what's your problem exactly but here is a SQL query that will do just what you have requested:
SELECT Person, salary, Age
FROM Table1 FULL OUTER JOIN Table2
WHERE Table1.Person = Table2.Person
Edit: This won't work on MS-ACCESS for its lack of support for FULL OUTER JOINS, the other two answers have explained the alternative.

Related

How to join a table with itself based on a foreign key in same table?

Let's say I have a SQL table as follows:
Id | Name | Email | Id_manager
---+------+--------------+------------
1 | Jon | jon#foo.com | 2
2 | Mike | mike#foo.com | 2
2 | Bar | bar#foo.com | 1
So here Jon is the manager of Bar and mike is the manager of John and himself. So Id_manager is a foreign key that references the same table.
I need to return a new table containing the following columns
Name, Email, Manager_Name
But I have no clue how to get the name of the manager using a SQL operation. Should I use a join? If so how can I do it in this case?
That's a self-join indeed:
select t.name, t.email, m.name as manager_name
from mytable t
inner join mytable m on m.id = t.id_manager
If there are employees without a manager, you might want to use left join instead of inner join to avoid filtering them out.
I think the answer can also be put in this way:
select t1.name, t1.email, t2.name as manager_name from mytable t1, mytable t2
where t1.id_manager = t2.id
I think the Id column should be unique, so I change the Id of Bar from 2 to 3.
The following can tell you the result when the id_manager column in t1 is equal to the Id column in t2.
t1 t2
Id|Name|Email |Id_manager Id|Name|Email |Id_manager
1 |Jon |jon#foo.com |2 2 |Mike|mike#foo.com|2
2 |Mike|mike#foo.com|2 2 |Mike|mike#foo.com|2
3 |Bar|bar#foo.com |1 1 |Jon |jon#foo.com |2

Select distinct values in same column by group

Using Microsoft Access and having a hard time figuring out how to get the desired results. I have two linked tables with an inner join on [bed] with the following data in both tables. I am looking to select [room number] that has a [gender] mismatch (has more than one distinct value per room number). I have searched stackoverflow and haven't found anything that seems to both group AND select distinct by group [room number].
Table 1
-----------------
Room Number | Bed
101 | 101a
101 | 101b
101 | 101c
102 | 102a
102 | 102b
103 | 103a
103 | 103b
Table 2
-----------------
Bed | Gender
101a | Male
101b | Male
101c | Female
102a | Male
102b | Male
103a | Female
103b | Undefined
With this data set, I would expect it to return Room 101 and 103 with the associated genders.
SQL Query
SELECT ROOM_NO
FROM RMGT_T_ROOMS INNER JOIN RMGT_T_ROOM_CONFIGS ON RMGT_T_ROOMS.PK_BED_SPACE = RMGT_T_ROOM_CONFIGS.CK_BED_SPACE
GROUP BY RMGT_T_ROOMS.FK_ROOM_NO
HAVING COUNT(DISTINCT GENDER) > 1
You could join that table on the bed's id and count the distinct number of genders:
SELECT room_number
FROM t1
JOIN t2 ON t1.bed = t2.bed
GROUP BY room_number
HAVING COUNT(DISTINCT gender) > 1
How about inner join and group by?
select t1.room
from t1 inner join
t2
on t1.bed = t2.bed
group by t1.room
having min(gender) <> max(gender);
If you know there are two genders only, you can add min(gender) and max(gender) to the select.
Another method uses exists:
select t1.room, t2.gender
from t1 inner join
t2
on t1.bed = t2.bed
where exists (select 1
from t1 as t11 inner join
t2 as t22
on t11.bed = t22.bed
where t22.gender <> t2.gender
);

Where clause to check against two columns in another table

I am struggling to get this answer for some reason.
I have two tables, table1 and table2 which look like this:
Table1:
ID Location Warehouse
1 London Narnia
2 Cyprus Metro
3 Norway Neck
4 Paris Triumph
Table2:
ID Area Code
1 London Narnia
2 Cyprus Metro
3 Norway Triumph
4 Paris Neck
I need to first select everything from table1 where table1.Location is in table2.Area AND table1.Warehouse is in table2.Code GIVEN THAT table1.Location is in table2.Area. I.e. I want:
ID Location Warehouse
1 London Narnia
2 Cyprus Metro
I have got to:
select
1.location
, 1.warehouse
from table1 1
where 1.location in (select area from table2)
and 1.warehouse in (select code from table2)
But this won't work because I need the second where clause to be executed based on the first where clause holding true.
I have also tried similar queries with joins to no avail.
Is there a simple way to do this?
Use exists:
select t.location, t.warehouse
from table1 t
where exists (select 1
from table2 t2
where t.location = t2.area and t.warehouse = t2.code
);
I should point out that some databases support row constructors with in. That allows you to do:
select t.location, t.warehouse
from table1 t
where(t1.location, t1.warehouse) in (select t2.area, t2.code from table2 t2);
Maybe I'm missing something, but a simple join on the two conditions would give you the result in your example:
select t1.*
from table1 t1
join table2 t2 on t1.Location = t2.Area
and t1.Warehouse = t2.Code;
Result:
| ID | Location | Warehouse |
|----|----------|-----------|
| 1 | London | Narnia |
| 2 | Cyprus | Metro |
Sample SQL Fiddle
You need to use JOIN.
I'll design the query in a while :)
EDIT:
SELECT
1.location
, 1.warehouse
FROM table1 1
JOIN table2 2 ON 1.location = 2.area AND 1.warehouse = 2.code

How can I query this in a database?

I have 2 tables
Table 1
Positon | Name | Nickname | Address
------------------------------------
1 | 2 | 3 | 4
5 | 6 | | 7
5 | 6 | | 8
Table 2
Detail_seq | Details
--------------------
1 | manager
2 | Jimmy
3 | Jim
4 | Chicago
5 | Supervisor
6 | Mike
7 | Vancouver
8 | New York
and the output should be like this or something
Position: Manager
Name: Jimmy
Nickname: Jim
Address: Chicago
Position: Supervisor
Name: Mike
Nickname:
Address: Vancouver and New York
feel free to ask questions if it is not clear.
thanks in advance
I think this is what you want:
SELECT Position=manager.details,
Name=Name.details,
Nickname=Nickname.details,
Address=Address.details
FROM table1 t1
LEFT OUTER JOIN table2 manager
ON t1.positon = manager.detail_seq
LEFT OUTER JOIN table2 name
ON t1.name = name.detail_seq
LEFT OUTER JOIN table2 Nickname
ON t1.nickname = Nickname.detail_seq
LEFT OUTER JOIN table2 Address
ON t1.address = Address.detail_seq
DEMO
It's a little bit extreme to store data this way. I can offer you to store the data categories in different tables. but if you insist, this should work
SELECT d1.details, d2.details, d3.details, d4.details
FROM main m, details d1, details d2, details d3, details d4
WHERE m.position = d1.detail_seq
AND m.name = d2.detail_seq
AND m.nickname = d3.detail_seq
AND m.adress = d4.detail_seq
You need to join the details table one time for every detail:
SELECT pos.Details, name.details, nick.details, adress.details
FROM table1 t1
LEFT JOIN table2 pos ON pos.detail_seq = t1.position
LEFT JOIN table2 name ON name.detail_seq = t1.name
LEFT JOIN table2 nick ON nick.detail_seq = t1.nickname
LEFT JOIN table2 address ON address.detail_seq = t1.address
select (select details from t2 where t2.detail_seq=t1.position) position,
(select details from t2 where t2.detail_seq=t1.name) Name,
(select details from t2 where t2.det_seq=t1.nickname) nickname,
(select details from t2 where t2.det_seq=t1.address) address
from t1 ;

SQL Select colmn from other table only if data exist

I have two tables and I'm selecting data from the first table. If the condition is meet(Alias type = 2) and the data in second table for the id from the first table exist the I want to select the column from the second table. Here is data to explain more:
Table 1
id | Name | Location
---+--------------+---------
34 |John Smith |NewYork
36 |Mike Smith |London
45 |Bob Smith |Los Angeles
Table 2
id | Alias | Alias type
---+-------------------+-------
36 |Warren Johnson |1
36 |William Williams |2
Wanted results if alias type = 2
id |Name | Location
---+-------------------+---------
34 |John Smith |NewYork
36 |William Williams |London
45 |Bob Smith |Los Angeles
Can you help me write query to get the wanted results? Tell me if I need to explain more. I'm using a SQL Server database.
You can use a left outer join onto Table2, and then COALESCE the Alias and Name results like this:
SELECT Table1.ID, COALESCE(Table2.Alias, Table1.Name) AS Name,
Table1.Location
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.ID AND Table2.AliasType = 2
COALESCE works by finding the first non-null value in the supplied values.
Try something like this -- you just need to use CASE:
SELECT T1.Id,
CASE WHEN T2.Alias IS NOT NULL THEN T2.Alias ELSE T1.Name END as Name,
t1.Location
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.Id = T2.Id AND T2.AliasType = 2
Here is the SQL Fiddle.
Good luck.
The COALESCE function will let you have a fall-back expression so that the name from table 2 is used if it exists, and the name from table 1 is used otherwise. The LEFT outer join only joins table 2 when the rows exist, and t2.name is null if no record was joined.
SELECT t1.id, COALESCE(t2.name, t1.name), t1.location FROM [Table 1] as t1 LEFT JOIN [Table 2] as t2 on t1.id=t2.id and t2.[alias type]=2