I have to two tables, both have a composite primary key:
OrderNr + CustNr
OrderNr + ItemNr
Can I join both tables with the OrderNr and OrderNr which is each a part of a composite primary key?
Yes, but you may find you get rows from each table that repeat as they combine to make a unique combination. This is called a Cartesian product
Table A
OrderNr, CustNr
1,C1
1,C2
2,C1
2,C2
TableB
OrderNr,ItemNr
1,i1
1,i2
SELECT * FROM a JOIN b ON a.OrderNr = b.OrderNr
1,C1,1,i1
1,C1,1,i2
1,C2,1,i1
1,C2,1,i2
This happens because composite primary keys can contain repeated elements so long as the combination of elements is unique. Joining on only one part of the PK, and that part being an element that is repeated (my custnr 1 repeats twice in each table, even though the itemnr and CustNr mean the rows are unique) results in a multiplied resultset - 2 rows from A that are custnr 1, multiplied by 2 rows from B that are custnr 1, gives 4 rows in total
Does it work with the normal/naturla join too?
Normal joins (INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER) will join the rows from two tables or subqueries when the ON condition is valid. The clause in the ON is like a WHERE clause, yes - in that it represents a statement that is true or false (a predicate). If the statement is true, the rows are joined. You don't even have to make it about data from the tables - you can even say a JOIN b ON 1=1 and every rows from A will get joined to every row from B. As commented, primary keys aren't involved in JOINS at all, though primary keys often rely on indexes and those indexes may be used to speed up a join, but they aren't vital to it.
Other joins (CROSS, NATURAL..) exist; a CROSS join is like the 1=1 example above, you don't specify an ON, every row from A is joined to every row from B, by design. NATURAL JOIN is one to avoid using, IMHO - the database will look for column names that are the same in both tables and join on them. The problem is that things can stop working in future if someone adds a column with the same name but different content/meaning to the two tables. No serious production system I've ever come across has used NATURAL join. You can get away with some typing if your columns to join on are named the same, with USING - SELECT * FROM a JOIN b USING (col) - here both A and B have a column called col. USING has some advantages, especially over NATURAL join, in that it doesn't fall apart if another column of the same name as an existing one but it has some detractors too - you can't say USING(col) AND .... Most people just stick to writing ON, and forget USING
NATURAL join also does NOT use primary keys. There is no join style (that I know of) that will look at a foreign key relationship between two tables and use that as the join condition
And then is it true that if I try to join Primary key and foreign key of two tables, that it works like a "where" command?
Hard to understand what you mean by this, but if you mean that A JOIN B ON A.primarykey = B.primary_key_in_a then it'll work out, sure. If you mean A CROSS JOIN B WHERE A.primarykey = B.primary_key_in_a then that will also work, but it's something I'd definitely avoid - no one writes SQLs this way, and the general favoring is to drop use of WHERE to create joining conditions (you do still see people writing the old school way of FROM a,b WHERE a.col=b.col but it's also heavily discouraged), and put them in the ON instead
So, in summary:
SELECT * FROM a JOIN b ON a.col1 = b.col2
Joins all rows from a with all rows from b, where the values in col1 equal the values in col2. No primary keys are needed for any of this to work out
You can join any table if there is/are logical relationship between them
select *
from t1
JOIN t2
on t1.ORderNr = t2.OrderNr
Although if OrderNr cannot provide unicity between tables by itself, your data will be multiplied.
Lets say that you have 2 OrderNr with value 1 on t1 and 5 OrderNr with value 1 on t2, when you join them, you will get 2 x 5 = 10 records.
Your data model is similar to a problem commonly referred to as a "fan trap". (If you had an "order" table keyed solely by OrderNr if would exactly be a fan trap).
Either way, it's the same problem -- the relationship between Order/Customers and Order/Items is ambiguous. You cannot tell which customers ordered which items.
It is technically possible to join these tables -- you can join on any columns regardless of whether they are key columns or not. The problem is that your results will probably not make sense, unless you have more conditions and other tables that you are not telling us about.
For example, a simple join just on t1.OrderNr = t2.OrderNr will return rows indicating every customer related to the order has ordered every item related to the order. If that is what you want, you have no problem here.
Related
I have two tables of world countries Independence Day and I wanted to combine them into one table with a distinct id, but they are using different Primary keys, any suggestions will be appreciated.
Summary of request: How to combine two tables with different Primary Keys but the other fields in common and removing duplicate fields ideally Hash Match and removing duplicates
Expected Results this will include all the unique countries in both tables, please one table may have more countries and we want to make sure we take all the distinct countries from each table. Ideally, the solution will be likely to be of like Hash Match operator in SQL which implements several different logical operations that all use an in-memory hash table for finding matching data. Many thanks in advance
The image of two tables which needs combining.
You seem to want full join:
select a.*, b.* -- select the columns you want
from a full join
b
on a.country = b.country;
If you want to assign a new unique id use row_number():
select row_number() over (order by coalesce(a.country, b.country)) as new_id,
a.*, b.* -- select the columns you want
from a full join
b
on a.country = b.country;
So, this is probably gonna sound like a weird or dumb question.
I have this application that I'm writing, which consists of four tables. Two are 'connected' to one main table, and one last one is connected to one of those two tables. I've included a database diagram to give you a better idea of what I mean.
Now, my goal is to have 'Bedrijfsnaam' from the 'Bedrijven' table into the 'Samenwerkingen' table. Problem is: I can't add more than two foreign keys, so I was assuming that I would have to create a FK in'Contactpersonen' table and pick it from the 'Bedrijven' table. It would basically mean I'd have a JOIN in 'Contactpersonen' table to my 'Bedrijven' table. And then the 'Samenwerkingen' table has a JOIN to the 'Contactpersonen' table and accesses the column from 'Bedrijven'.
Does that make any sense? Hope it does, because I could really use some help making this possible. xD
Since Samenwerkingen has a foreign key to Contactpersonen which is itself related to Bedrijven, you don't need an additional constraint: your data integrity is guaranteed and you can join the two tables.
Your query should look like :
select s.*, b.* from Samenwerkingen s
inner join Contactpersonen c on s.Contactpersonen = c.Contactpersonen
inner join Bedrijven b on c.Bedrijfnaam = b.Bedrijfnaam
I'm designing a table that will hold numeric values for 2-3 situations of data:
Situation 1: has Age and Sex, along with the numeric value
Situation 2: has only Age, along with the numeric value
Situation 3: has only Sex, along with the numeric value
I don't want to create 3 different tables. Instead, only one table, with the following columns:
AgeID (references a table that contains information about the Age)
SexID (references a table that contains information about the Age)
Value (the numeric value itself)
AgeID and SexID as Foreign Keys and linked to the appropriate tables.
The problem is: my query is always doing a INNER JOIN with Age and Sex tables. For Situation 1 it works well because values are present. For Situations 2 and 3 I don't get any data, because either AgeID or SexID is null.
What solution is the correct one?
Change something in the table design?
Use Entity-Attribute-Value table to be more generic?
Use LEFT JOIN instead of INNER JOIN for all queries involving the nullable columns??
Any other idea?
Could someone clarify?
Thanks!
Yes an outer Join, Left or right, the Inner join is meant to filter out everything that doesn't have a match in both tables.
Use a conditional INNER JOIN, like
INNER JOIN Table x ON
(AgeID IS NULL OR AgeID = x.AgeID)
AND (SexID IS NULL OR SexID = x.SexID)
If I say:
A NATURALJOIN B
Is that the same as:
B NATURALJOIN A
Similarly, if I say:
A NATURALJOIN B NATURALJOIN C
How is that supposed to be evaluated?
Here are my remarks:
NATURALJOIN is two words: NATURAL JOIN
The order of the tables makes no difference. Exception: when you SELECT *, then the list of selected columns is all columns of the first table, then all columns of the second table.
Don't use NATURAL JOINs. It joins tables by their common columns. If the tables happen to share a column name like "text", "description" or "name" this will be used. Imagine you write a program with a SELECT statement, where two tables person and job are joined by person_id. Later you add a column "description" to both tables. Suddenly your program will fail completely to get any matching record, because "person_id" may match, but "description" won't.
I have a database with two tables
One with games
and one with participants
A game is able to have more participants and these are in a different table.
Is there a way to combine these two into one query?
Thanks
You can combine them using the JOIN operator.
Something like
SELECT *
FROM games g
INNER JOIN participants p ON p.gameid = g.gameid
Explanation on JOIN operators
INNER JOIN - Match rows between the two tables specified in the INNER
JOIN statement based on one or more
columns having matching data.
Preferably the join is based on
referential integrity enforcing the
relationship between the tables to
ensure data integrity.
o Just to add a little commentary to the basic definitions
above, in general the INNER JOIN
option is considered to be the most
common join needed in applications
and/or queries. Although that is the
case in some environments, it is
really dependent on the database
design, referential integrity and data
needed for the application. As such,
please take the time to understand the
data being requested then select the
proper join option.
o Although most join logic is based on matching values between
the two columns specified, it is
possible to also include logic using
greater than, less than, not equals,
etc.
LEFT OUTER JOIN - Based on the two tables specified in the join
clause, all data is returned from the
left table. On the right table, the
matching data is returned in addition
to NULL values where a record exists
in the left table, but not in the
right table.
o Another item to keep in mind is that the LEFT and RIGHT OUTER
JOIN logic is opposite of one another.
So you can change either the order of
the tables in the specific join
statement or change the JOIN from left
to right or vice versa and get the
same results.
RIGHT OUTER JOIN - Based on the two tables specified in the join
clause, all data is returned from the
right table. On the left table, the
matching data is returned in addition
to NULL values where a record exists
in the right table but not in the left
table.
Self -Join - In this circumstance, the same table is
specified twice with two different
aliases in order to match the data
within the same table.
CROSS JOIN - Based on the two tables specified in the join clause, a
Cartesian product is created if a
WHERE clause does filter the rows.
The size of the Cartesian product is
based on multiplying the number of
rows from the left table by the number
of rows in the right table. Please
heed caution when using a CROSS JOIN.
FULL JOIN - Based on the two tables specified in the join clause,
all data is returned from both tables
regardless of matching data.
example
table Game has columns (gameName, gameID)
table Participant has columns (participantID, participantName, gameID)
the GameID column is the "link" between the 2 tables. you need a common column you can join between 2 tables.
SELECT gameName, participantName
FROM Game g
JOIN Participat p ON g.gameID = p.gameID
This will return a data set of all games and the participants for those games.
The list of games will be redundant unless you structure it some other way due to multiple participants to that game.
sample data
WOW Bob
WOW Jake
StarCraft2 Neal
Warcraft3 James
Warcraft3 Rich
Diablo Chris