Joining 2 tables ON a column with some missing entries - sql

Consider these 2 tables:
CustAddress
Name Address
---- -------
John 116 States Ave
Mike 404 16th Street
CustPhone
Name Phone
---- -------
John 342-345-456
Smith 678-435-567
How do I combine these into a single result like this in Oracle:
Customer info with Address and Phone:
Name Phone Address
---- ------- -------
John 342-345-456 116 States Ave
Smith 678-435-567
Mike 404 16th Street
Full Outer Join doesn't help as I end up losing some data.
Here is a SQL Fiddle to play with:
http://sqlfiddle.com/#!9/ebb9b/1

Using a full join.
select coalesce(ca.name,cp.name) as name, cp.phone, ca.address
from custaddress ca
full join custphone cp on ca.name=cp.name
Or using union all assuming there is at most one record per name in either of the tables.
select name,max(phone) as phone,max(address) as address
from (select name,phone,null as address from custphone
union all
select name,null,address from custaddress
) x
group by name

Kinda ugly but
select Names.Name, CustAddress.Address, CustPhone.Phone from
(select Name from CustAddress union select Name from CustPhone) as Names
left join CustAddress on Names.Name = CustAddress.Name
left join CustPhone on Names.Name = CustPhone.Name;

Related

How can I create a BigQuery record with a join, but without specifying all fields?

Question: How to join tables using join clause without listing all the fields?
Data
Given two tables, Person and Address:
Person
name
address_id
Alice
10
Bob
11
Charlie
10
Address
id
street
city
10
William Street
NYC
11
Old Street
London
Desired result:
I'd like to join them with a record, like so:
name
address.street
address.city
Alice
William Street
NYC
Bob
Old Street
London
Charlie
William Street
NYC
However, I have many columns in both tables and I don't want to specify them all.
So something a bit like using EXCEPT but with the joined columns becoming nested in an address record:
SELECT * EXCEPT (address_id)
FROM person p
JOIN address a
ON p.address_id = a.id
Is this possible in BigQuery?
Consider below query:
SELECT p.* EXCEPT(address_id), (SELECT AS STRUCT a.* EXCEPT(id)) AS address
FROM Person p JOIN Address a ON p.address_id = a.id;
output:
You can join more tables with similar approach.
SELECT p.* EXCEPT(address_id),
(SELECT AS STRUCT a.* EXCEPT(id)) AS address,
(SELECT AS STRUCT j.* EXCEPT(name)) AS Job
FROM Person p
JOIN Address a ON p.address_id = a.id
JOIN Job j ON p.name = j.name;
output:

SQL query on similarity

I have to display all the customers who have been referred by a referrer with the same last name as the customer.
You can use a self-join as
select c1.customer#, c1.lastname, c1.city, c1.zip, c1.referred
from customers c1
join customers c2
on c1.customer# = c2.referred
and c1.lastname = c2.lastname;
customer# lastname city zip referred
--------- -------- ----------- ------ ---------
1003 SMITH TALLAHASSEE 32306 NULL
Rextester Demo
You can try this query
select cust.*, cust_ref.*
from customers cust,
referred cust_ref
where cust_ref.lastname = cust.lastname
Note : You can select field according your requirement.
I hope it will used.

How to compare two different tables based on two different Columns in SQL Server?

The first table consists of Accounts with State and Country information which are mostly correct with few wrong rows:
ID NAME State Country
--------------------------------------------------
1 Account 1 NJ USA
2 Account 2 NY NULL
3 Account 3 Beijing Japan
And I have the second table which has the correct state and County information to which the first tables needs to be compared to:
State_Code State Country_Code Country
-------------------------------------------------------
01 NJ A01 USA
02 NY A01 USA
03 Beijing c01 China
The query should check if the state in the first table exists in the second table and if it does, is it associated with the correct country and the result would be a table of rows with wrong info:
So in my example, the comparison should give me the result:
ID NAME State Country
------------------------------------------------------
2 Account 2 NY NULL
3 Account 3 Beijing Japan
I am a beginner trying to learn more about SQL and I tried solving this using left join and outer join both of which didn't give me the correct result. I would be very grateful if some one could point me in the right direction or give me an example on how I should approach this.
(I am using Microsoft SQL Server Management Studio)
Please try this. You can change the join condition if you need any changes.
Data
CREATE TABLE firstTable
(
ID INT
,NAME VARCHAR(10)
,State VARCHAR(10)
,Country VARCHAR(10)
)
GO
INSERT INTO firstTable VALUES
(1 ,'Account 1','NJ','USA'),
(2 ,'Account 2','NY',NULL),
(3 ,'Account 3','Beijing','Japan')
GO
CREATE TABLE SecondTable
(
State_Code VARCHAR(10)
,State VARCHAR(10)
,Country_Code VARCHAR(10)
,Country VARCHAR(10)
)
GO
INSERT INTO SecondTable VALUES
('01','NJ' ,'A01','USA'),
('02','NY' ,'A01','USA'),
('03','Beijing' ,'c01','China')
GO
SOLUTION
select f.* from firstTable f
FULL JOIN SecondTable s
ON f.State = s.State and f.Country = s.Country
WHERE f.State IS NOT NULL AND ( s.Country_Code IS NULL OR s.State IS NULL )
OUTPUT
ID NAME State Country
----------- ---------- ---------- ----------
2 Account 2 NY NULL
3 Account 3 Beijing Japan
(2 rows affected)
You want to join the two tables on the State and look for records where the Country doesn't match. This query should get you there:
SELECT t1.*, t2. Country AS Expected
FROM table1 t1
JOIN table2 t2 ON t1.State = t2.State
WHERE t1.County != t2.Country
Unfortunately, I don't know your table names, so I just had to go with table1 and table2, but hopefully this gives you what you need. I also added in the expected Country, but you can remove that if you don't need it.
I think what you're looking for is "NOT EXISTS". Basically you look for any state/country combos in the first table that don't exist in the second table. Here's an example.
SELECT tbo.ID, tbo.NAME, tbo.STATE, tbo.COUNTRY
FROM TableOne tbo
WHERE NOT EXISTS(
SELECT * FROM TableTwo tbt
WHERE tbo.State = tbt.State
AND tbo.Country = tbt.Country
)

How to use 2 instances of the same table

I am wondering how to use 2 instances of the same table in the following example , I know how to do it but I just cant make it work for my task.
I have the following tables :
Agency(id_agency,name)
Space(id_space,address)
Offer(id_agency,id_space)
Task: Find out the address,agency name 1 ,agency name 2 for spaces offered by two different agencies(the combination of 2 agencies is unique).
What I tried:
1)
SELECT ADDRESS,A.NAME,B.NAME
FROM AGENCY A
INNER JOIN OFFER O ON A.ID_AGENCY=O.ID_AGENCY
INNER JOIN SPACE S ON O.ID_SPACE=S.ID_SPACE
WHERE S.ID_SPACE=ANY(SELECT S.ID_SPACE FROM AGENCY B
INNER JOIN OFFER O ON B.ID_AGENCY=O.ID_AGENCY
INNER JOIN SPACE S ON O.ID_SPACE=S.ID_SPACE
);
2)
SELECT ADDRESS
FROM AGENCY A
INNER JOIN OFFER O ON A.ID_AGENCY=O.ID_AGENCY
INNER JOIN SPACE S ON O.ID_SPACE=S.ID_SPACE
INTERSECT
SELECT ADDRESS
FROM AGENCY B
INNER JOIN OFFER O ON B.ID_AGENCY=O.ID_AGENCY
INNER JOIN SPACE S ON O.ID_SPACE=S.ID_SPACE
WHERE A.ID_AGENCY<>B.ID_AGENCY;
In the second example I have no idea how to make it show A.name and b.name, since intersect won't work if I try to add them...
I tried to do this for the last 3 hours , sadly, I guess I can`t do it with the skills I have so far. :(
Thanks in advance
Edit 1: I hope you understand, thats how it should look.
Agency
id_agency name
---------- -------
1 Agency1
2 Agency2
3 Agency3
Space
id_space address
--------- --------
1 address1
2 address2
3 address3
Offer
id_agency id_space
----------- --------
1 1
2 1
3 2
Expected output:
Address Name1 Name2
----------- -------- -------
address1 Agency1 Agency2
To have the results in 1 row, each pair of agencies per row, as you asked for:
select S.address as address, A1.name as agency_1, A2.name as agency_2
from offer O1
join offer O2
on O2.id_space = O1.id_space
and O2.id_agency != O1.id_agency
join space S
on S.id_space = O1.id_space
join agency A1
on A1.id_agency = O1.id_agency
join agency A2
on A2.id_agency = O2.id_agency
;
The "core functionality" here is the join of offer no.1 (O1 alias) to offer no.2 (O2 alias) on equality of id_space but difference of id_agency.
An interesting exercise: To have the results in multiple rows, one agency per row:
select S.address, A.name as agency, X.number_of_agencies_per_space
from (
select id_space, id_agency, count(1) over (partition by id_space) as number_of_agencies_per_space
from offer
) X
join space S
on S.id_space = X.id_space
join agency A
on A.id_agency = X.id_agency
where X.number_of_agencies_per_space > 1
;

Having trouble creating join looking for specific data

I am using Oracle SQL (TeraTerm),
and
I am trying to join specific information from two tables CONSULTANT, and PROJECT_CONSULTANT, and I need to retrieve only the employees who worked over 40 hours. Here are the tables
Project Consultant
PROJECT_ID CONSULTANT_ID NUMBER_HOURS
--------------- --------------- ------------
94738949 49620928 6
45699847 34879223 57
45699847 95928792 44
45699847 04875034 59
19870398 49620928 32
30495394 95928792 57
30495394 07811473 50
62388923 07811473 82
and Consultant
CONSULTA NAME ZIP START_DT
-------- -------------------------------- ----- ---------
CON_TITLE
-------------------------
49620928 Tom Jones 39875 01-SEP-98
Junior Consultant
04875034 Jack Johnson 29087 05-OCT-93
Manager
34879223 Lanny Harris 03944 30-APR-04
Principal
CONSULTA NAME ZIP START_DT
-------- -------------------------------- ----- ---------
CON_TITLE
-------------------------
95928792 Michael Johnson 02953 22-JUN-02
Senior Manager
07811473 Wendy Adams 29087 05-JUL-05
Senior Consultant
The code I came up with is
select Consultant_ID, Name, Zip, and Number_Hours
from Consultant
Inner Join project_consultant
ON Consultant.Consultant_ID=project_consultant.Consultant_ID
WHERE project_consultant.number_Hours>40;
I am getting an error
ERROR at line 1:
ORA-00936: missing expression
I just wanna know how to write the join statement correctly any help would be awesome, because I am having trouble knowing how to fix this join statement
You don't use and in the select clause:
select c.Consultant_ID, c.Name, c.Zip, pc.Number_Hours
from Consultant c Inner Join
project_consultant pc
on c.Consultant_ID = pc.Consultant_ID
where pc.number_Hours > 40;
You also need a table alias in the select clause to be clear what table Consultant_Id refers to.
EDIT:
You might actually want to sum the hours for employees. If so, you need an aggregation:
select c.Consultant_ID, c.Name, c.Zip, sum(pc.Number_Hours)
from Consultant c Inner Join
project_consultant pc
on c.Consultant_ID = pc.Consultant_ID
group by c.Consultant_ID, c.Name, c.Zip
having sum(pc.number_Hours) > 40;
You can't use and in Select Clause
Try this
SELECT C.Consultant_ID, C.Name, C.ip, PC.Number_Hours
FROM Consultant C
INNER Join project_consultant PC
ON C.Consultant_ID=PC.Consultant_ID
WHERE PC.number_Hours > 40;
select c.Consultant_ID, c.Name, c.Zip, p.Number_Hours
from Consultant c
Inner Join project_consultant p
ON c.Consultant_ID=p.Consultant_ID
WHERE p.number_Hours>40;