SQL join tables without common key - sql

New to SQL. I'm working with AdventureWorks 2012 trying to familiarize myself with SQL server. Having trouble joining tables that don't share a common key. Can this be done?
If you're familiar with the AdventureWorks DB I'm trying to return the Name (FirstName, MIddleName, LastName), AddressType, and Address (Combination of AddressLine1, Address Line2, City, State, PostalCode) but that draws from 3 different tables and they don't share any key that can link them together.

If the two tables does not share any common key, make sure a third table exits that acts as bridge between those two table.
For Example, Table A, and Table C may not have any common key. But in a database, it will be possible to have third table Table B which can able to join with Table A as well as Table C. So using the Table B you can bring together table A and Table C (Logically by the way it is designed).

They may not have a direct key but they are related: You have to learn how to navigate the foreign keys to use the model as it was intended. Have a look at this diagram of the AdventureWorks data model that ships with SQL 2008. In particular pay attention to the Person section (in a sort of beige colour near the centre).
Person is linked to address by way of BusinessEntity and BusinessEntityAddress therefore your query needs to join these tables to get the info you want. So, your query will look a bit like this:
SELECT .pFirstName, p.MiddleName, P.LastName, at.[Name], a.AddressLine1, a.AddressLine2, a.City, a.State, a.PostalCode
FROM Person p
INNER JOIN BusinessEntity be
ON be.BusinessEntityId = p.BusinessEntityId
INNER JOIN BusinessEntityAddress bea
ON bea.BusinessEntityId = be.BusinessEntityId
INNER JOIN AddressType at
ON at.AddressTypeId = bea.AddressTypeId
INNER JOIN Address a
ON a.AddressId = bea.AddressId
I don't have AdventureWorks to hand to test it but that should give you the basic idea. You have to follow the keys otherwise you won't get the data you want or expect.

Try something like this:
select t1.firstname, t1.middlename, t1.lastnme,
t2.addresstype,
t3.addresslin1, t3.addresslin2, t3.city
from table1 t1, table2 t2, table3 t3;

select <fields list> from table1
union all
select <the same fields list> from table2
union all
select <the same fields list> from table3
Join them with UNION ALL (or you can use UNION if you should skip duplicates)

Related

How to join two tables with unrelated columns SQL

I am trying to join two tables together using UNION (although im not sure that is the best option) there are technically two related columns however they don't have the same name so i'm assuming that isn't an option here is my query:
SELECT title, type, release_date FROM pictures
UNION
SELECT name, residence, NULL as Col3 FROM actor
ORDER BY release_date ASC;
It is only printing out the pictures columns from this? Thank you for any help in advance.
To relate two tables you could use some foreign key or a third table in the case of beign a many-to-many relation, you should use one of the join options, for example:
Imagine that exists a table that relate actor and pictures, called actor_pictures.
Image that we will relate the tables by id (it could be another one, and it doesn't have to have the same name).
You could do this:
SELECT * FROM actor_pictures ap
JOIN actor a ON ap.actor_id = a.id
JOIN pictures p ON ap.pictures_id = p.id
ORDER BY p.release_date ASC
Read this: https://www.w3schools.com/sql/sql_join.asp

PostgreSQL - copy column from related table

So I have three tables: companies, addresses and company_address.
For optimization reasons I need to copy city column from addresses table to companies table. Relation between companies and addresses is many to one (as many companies can occupy same address). They are connected through company_address table, consisting of address_id and company_id columns.
I found this solution for case without intermediate table: How to copy one column of a table into another table's column in PostgreSQL comparing same ID
Trying to modify query I came up with:
UPDATE company SET company.city=foo.city
FROM (
SELECT company_address.company_id, company_address.address_id, address.city
FROM address LEFT JOIN company_address
ON address.id=company_address.address_id
) foo
WHERE company.id=foo.company_id;
but it gives error:
ERROR: column "company" of relation "company" does not exist
I cant figure out what is going on. I'll be grateful for any ideas.
You don't need a subquery for that. Also, refer in the SET clause to your table columns without preceding with table name.
I believe that since your WHERE condition includes joined table, it should be INNER JOIN instead of a LEFT JOIN.
UPDATE company c
SET city = a.city
FROM address a
INNER JOIN company_address ca ON a.id = ca.address_id
WHERE c.id = ca.company_id
Note how using aliases for table names shortens the code and makes it readable at the very first glance.
You're right syntactically, you just don't need the table name at the beginning of the update statement:
UPDATE company SET city=foo.city
FROM (
SELECT company_address.company_id, company_address.address_id, address.city
FROM address LEFT JOIN company_address
ON address.id=company_address.address_id
) foo
WHERE company.id=foo.company_id;

SQL query to pull data from three different tables

I have to create a SQL query to list all the Nurses in the ‘Sparrow’ Wing ordered by last name, first name.
However, I need to pull Nurse_name and Nurse_surname from the Nurse table, which is linked to another table called Sister by the foreign key Sister_ID, this table is then linked to another table called Wing which has the foreign key Sister_ID.
The nurse is managed by the sister and the sister manages the wing.
Can anyone help me with an SQL query for this? As it is, I am only able to get the data from nurse and sister tables.
Since you seem to be aware that you should use the inner join to connect tables (but apparently not that the connection needs to be via the related columns) you should apply that knowledge to connect all the tables you need to answer the query.
If you start at the end result and work your way backwards you first chose the columns you need:
select Nurse.Nurse_name, Nurse.Nurse_surname
and then as they belong to the Nurse table you use that as source in the from clause
from Nurse
to get the Wing you need to connect the Sister table, but to connect that and Nurse you first need the SisterNurse table joined on the shared attribute
join SisterNurse on Nurse.Nurse_ID = SisterNurse.Nurse_ID
now you can join Sister on the attribute shared with SisterNurse
join Sister on Sister.Sister_ID = SisterNurse.Sister_Id
and finally you can join Wing
join Wing on Wing.sister_ID = Sister.Sister_ID
limit the Wings to the one names 'Sparrow'
where Wing.Wing_Name = 'Sparrow'
and order the data
order by Nurse.Nurse_surname, Nurse.Nurse_name
Put it all together and you get:
select Nurse.Nurse_name, Nurse.Nurse_surname
from Nurse
join SisterNurse on Nurse.Nurse_ID = SisterNurse.Nurse_ID
join Sister on Sister.Sister_ID = SisterNurse.Sister_Id
join Wing on Wing.sister_ID = Sister.Sister_ID
where Wing.Wing_Name = 'Sparrow'
order by Nurse.Nurse_surname, Nurse.Nurse_name
You don't give much information about the schema involved but maybe this will help:
select
n.Nurse_name
, n.Nurse_surname
, w.Wing_name
, managing_nurse.Nurse_name
, managing_nurse.surname
from
Nurse n
join Sister s on n.Sister_ID=n.Sister_ID
join Wing w on s.Sister_ID=w.Sister_ID
join Nurse managing_nurse on w.Nurse_Manager_ID=managing_nurse.Sister_ID
A simple way is to use 'union':
select * from (
select nurse_name, nurse_surname, 'nurse' as nurse_type from nurse_table
union
select nurse_name, nurse_surname, 'sister' as nurse_type from syster join nurse_table on nurse_table.syster_id = syster.syster_id
union
select nurse_name, nurse_surname, 'wing' as nurse_type from wing join syster on wing.syster_id = syster.syster_id join nurse_table on nurse_table.syster_id = syster.syster_id )
order by nurse_surname, nurse_name
Hope this help you!
P.S.
I assume that syster and wing tables have nurse_name and nurse_surname fields.
If not you have to give the same alias to all the selected columns

SQL WHERE <from another table>

Say you have these tables:
PHARMACY(**___id_pharmacy___**, name, addr, tel)
PHARMACIST(**___Insurance_number___**, name, surname, qualification, **id_pharmacy**)
SELLS(**___id_pharmacy___**, **___name___**, price)
DRUG(**___Name___**, chem_formula, **id_druggistshop**)
DRUGGISTSHOP(**___id_druggistshop___**, name, address)
I think this will be more specific.
So, I'm trying to construct an SQL statement, in which I will fetch the data from id_pharmacy and name FROM PHARMACY, the insurance_number, name, and surname columns from PHARMACIST, for all the pharmacies that sell the drug called Kronol.
And that's basically it. I know I'm missing the relationships in the code I wrote previously.
Note: Those column names which have underscores left and right to them are underlined(Primary keys).
The query you've written won't work in any DBMS that I know of.
You'll most likely want to use some combination of JOINs.
Since the exact schema isn't provided, consider this pseudo code, but hopefully it will get you on the right track.
SELECT PH.Ph_Number, PH.Name, PHCL.Ins_Number, PHCL.Name, PHCL.Surname
FROM PH
INNER JOIN PHCL ON PHCL.PH_Number = PH.Ph_Number
INNER JOIN MLIST ON MLIST.PH_Number = PH.PH_Number
WHERE MLIST.Name = "Andy"
I've obviously assumed some relationships between tables that may or may not exist, but hopefully this will be pretty close. The UNION operator won't work because you're selecting different columns and a different number of columns from the various tables. This is the wrong approach all together for what you're trying to do. It's also worth mentioning that a LEFT JOIN may or may not be a better option for you, depending on the exact requirements you're trying to meet.
Ok, try this query:
SELECT A.id_pharmacy, A.name AS PharmacyName, B.Insurance_number,
B.name AS PharmacistName, B.surname AS PharmacistSurname
FROM PHARMACY A
LEFT JOIN PHARMACIST B
ON A.id_pharmacy = B.id_pharmacy
WHERE A.id_pharmacy IN (SELECT id_pharmacy FROM SELLS WHERE name = 'Kronol')

SQL query to get data from one table based upon a column from another table?

In my tables I have for example
CountyID,County and CityID in the county table and in the city table I have table I have for example
City ID and City
How do I create a report that pulls the County from the county table and pulls city based upon the cityid in the county table.
Thanks
Since this is quite a basic question, I'll give you a basic answer instead of the code to do it for you.
Where tables have columns that "match" each other, you can join them together on what they have in common, and query the result almost as if it was one table.
There are also different types of join based on what you want - for example it might be that some rows in one of the tables you're joining together don't have a corresponding match.
If you're sure that a city will definitely have a corresponding county, try inner joining the two tables on their matching column CityID and querying the result.
The obvious common link between both tables is CityID, so you'd be joining on that. I think you have the data organized wrong though, I'd put CountryID in the City table rather than CityID in the country table. Then, based on the CountryID selected, you can limit your query of the City table based on that.
To follow in context of Bridge's answer, you are obviously new to SQL and there are many places to dig up how to write them. However, the most fundamental basics you should train yourself with is always apply the table name or alias to prevent ambiguity and try to avoid using column names that might be considered reserved words to the language... they always appear to bite people.
That said, the most basic of queries is
select
T1.field1,
T1.field2,
etc with more fields you want
from
FirstTable as T1
where
(some conditional criteria)
order by
(some column or columns)
Now, when dealing with multiple tables, you need the JOINs... typically INNER or LEFT are most common. Inner means MUST match in both tables. LEFT means must match the table on the left side regardless of a match to the right... ex:
select
T1.Field1,
T2.SomeField,
T3.MaybeExistsField
from
SomeTable T1
Join SecondTable T2
on T1.SomeKey = T2.MatchingColumnInSecondTable
LEFT JOIN ThirdTable T3
on T1.AnotherKey = T3.ColumnThatMayHaveTheMatchingKey
order by
T2.SomeField DESC,
T1.Field1
From these examples, you should easily be able to incorporate your tables and their relationships to each other into your results...