Join two tables with one table - sql

I need to do the following (I am not really sure if it is possible to do using SQL)
Table A
col_a_1, col_a_2, col_a_3
Table B
col_a_1, col_b_1, col_b_2....
Table C
col_a_1, col_c_1, col_c_2....
were col_a_1 is unique in table A. I need to join tables A, B, C such that every entry in table A will appear multiple times but every entry in table B and C appears only once and against the same col_a_1 of table A.
I know how to do it using the code. Is it also possible to do with SQL alone?
Thanks in advance.

You either want to use an outer join of some sort. either left or full outer.
SELECT A.*, B.*, C.*
FROM Table_A A
LEFT JOIN Table_B B on A.col_A_1 = B.Col_A_1
LEFT JOIN table_C C on A.Col_A_1 = C.Col_A_1
SELECT A.*, B.*, C.*
FROM Table_A A
FULL OUTER JOIN Table_B B on A.col_A_1 = B.Col_A_1
FULL OUTER JOIN table_C C on A.Col_A_1 = C.Col_A_1
or possibly a union result... just depends on what you're after.
SELECT A.*, B.*
FROM Table_A A
INNER JOIN Table_B B on A.col_A_1 = B.Col_A_1
UNION
SELECT A.*, C.*
FROM Table_A A
INNER JOIN Table_C C on A.col_A_1 = C.Col_A_1

Related

perform or not perform a specific predicate in WHERE clause conditionally in SQL Oracle

Is there a way in SQL Oracle to perform a predicate in where clause conditionally depending if a record exist in a specific table.
Example
SELECT * FROM TABLE_A a, TABLE_B b, TABLE_C c
WHERE a.personalID = B.personalId
and b.companyID = c.companyID
When a specific company ID is NOT existing in Table_C then this part in where clause SHOULD not be perfomed as execute.
and b.companyID = c.companyID
Switch to modern, explicit JOIN syntax.
Do LEFT JOIN to handle "When a specific company ID is NOT existing in Table_C".
SELECT *
FROM TABLE_A a
JOIN TABLE_B b ON a.personalID = B.personalId
LEFT JOIN TABLE_C c ON b.companyID = c.companyID
Or, keep that ancient implicit join and do a UNION ALL:
SELECT * FROM TABLE_A a, TABLE_B b, TABLE_C c
WHERE a.personalID = B.personalId
and b.companyID = c.companyID
UNION ALL
SELECT a.*, b.*, some null's
FROM TABLE_A a, TABLE_B b
WHERE a.personalID = B.personalId
AND NOT EXISTS (select 1 from TABLE_C c
where b.companyID = c.companyID)

SQL join on three tables, lines that exist in 2 tables but not the third

Please I need your help.
Suppose that we have 3 tables A, B and C as shown in the image below:
I want to get lines in the table A that exist or not exist in table B, and lines in table C that exist or not exist in table B, using one sql request.
I have tried this but doesn't work :
SELECT A.ATS0804, C.ATS0207, A.ATS0959, A.ATS0802, B.ATS0827
FROM
ISUT183.ENS0042 B
RIGHT JOIN ISUT183.ENS0038 A
ON B.ENS0038K = A.ATS0804
RIGHT JOIN ISUT183.EN00041 C
ON B.EN00041K = C.AT02812
WHERE ( C.ATS0207 = '0001757430'
AND B.ATS0823 = '9999-01-01'
AND A.ATS0803 = '9999-01-01'
AND A.ATS0959 = '61384352001'
AND A.ATS0802 ='01.01.2010'
) ;
you can do a cross join too:
with AB as (
select * from A left outer join B on A.ID1=B.ID1
),
AC as (
select * from C left outer join B on C.ID2=B.ID2
)
select * from AB CROSS JOIN AC
use where exists and where not exists clauses
If you test equality into table B in where clause, the left outer join or right outer join dont take null
You dont have join between A and C, then you can do a UNION ALL
but you must take columns of same type in selects clause (ID1 same type of ID2)
select * from (
select 'A-B' typejoin, A.ID1 as IDA_OR_C, B.ID1 as IDB from A left outer join B on A.ID1=B.ID1
union all
select 'A-C' typejoin, C.ID2 as IDA_OR_C, B.ID2 as IDB from C left outer join B on C.ID2=B.ID2
) tmp
where ....

Do I have to do a LEFT JOIN after a RIGHT JOIN?

Say I have three tables in SQL server 2008 R2
SELECT a.*, b.*, c.*
FROM
Table_A a
RIGHT JOIN Table_B b ON a.id = b.id
LEFT JOIN Table_C c ON b.id = c.id
or
SELECT a.*, b.*, c.*
FROM
Table_A a
RIGHT JOIN Table_B b ON a.id = b.id
JOIN Table_C c ON b.id = c.id
also, does it matter if I use b.id or a.id on joining c?
i.e. instead of JOIN Table_C c ON b.id = c.id, use JOIN Table_C c ON a.id = c.id
Thank you!
If it doesn't change the semantics of the query, the database server can reorder the joins to run in whichever way it thinks is more efficient.
Usually, if you want to force a certain order, you can use inline view subqueries, as in
SELECT a.*, x.*
FROM
Table_A a
RIGHT JOIN
(
SELECT *, b.id as id2 FROM Table_B b
LEFT JOIN Table_C c ON b.id = c.id
) x
ON a.id = x.id2
According to the definitions:
JOIN
: Return rows when there is at least one match in both tables
LEFT JOIN Return all rows from the left table, even if there are no matches in the right table
RIGHT JOIN Return all rows from the right table, even if there are no matches in the left table
The first option would include all raws from the 1st Join on Tables a and b even if there are no matching ones in table c, while the second statement would show only raws which match ones in table c.
regarding the second question i guess it would make a difference, since the 1st join includes all ids from table b, even though there are no matching ones in table a, so once you change your Join creterium to a.id you will get a different set of ids than b.id.
Yes, you do need a LEFT JOIN after a RIGHT JOIN
See
http://sqlfiddle.com/#!3/2c079/5/0
http://sqlfiddle.com/#!3/2c079/6/0
If you don't, the (inner) JOIN at the end will cancel out the effect of your RIGHT JOIN.
That wouldn't make any sense to have a RIGHT JOIN if you don't care. And if you care, you will have to add a LEFT JOIN after it.

SQL joining/unioning help - link table b and c to table a?

I have 3 tables in my database. Each of them has one column, "index" that links the fields across all 3.
Our starting point is table a, and the indexes inside it. If the index is not there, I don't need it.
Tables b and c are very similar, and every index listed in table a will be in b or c, or both. All I need to do is make sure that all the fields in table a are joined to fields in table b or c.
I started with:
SELECT *
FROM `table_a`
JOIN table_b ON table_a.index = table_b.index
Which works great. But it will exclude all the indexes in table a which don't match, which is why I believe, when I add:
UNION
FROM `table_a`
JOIN table_c ON table_a.index = table_c.index
I actually get LESS results, rather than more.
Can someone tell me how to say "if the index isn't in table b, then look in table c?"
I'm not sure this is what you're after, but it will give you all the results of a, and any possible matches from b OR c.
SELECT *
FROM table_a
LEFT OUTER JOIN table_b ON table_a.index = table_b.index
LEFT OUTER JOIN table_c ON table_a.index = table_c.index
Did you try a "Union All" ?
SELECT *
FROM `table_a`
JOIN table_b ON table_a.index = table_b.index
UNION ALL
SELECT *
FROM `table_a`
JOIN table_c ON table_a.index = table_c.index
First step:
SELECT * FROM
table_a
LEFT JOIN table_b ON table_a.index = table_b.index
LEFT JOIN table_c ON table_b.index = table_c.index
This will get you all indexes from all 3 tables.
If you want to have the first index which isn't NULL from the tables _a, _b, or _c you can do this like this in MySQL:
SELECT COALESCE(table_a.index, table_b.index, table_c.index) AS firstIndexFromABC
FROM
table_a
LEFT JOIN table_b ON table_a.index = table_b.index
LEFT JOIN table_c ON table_b.index = table_c.index
Or what DB are you using? Update: MySQL
Update after some comments:
Sorry, I still don't get it. That's what the COALESCE method does. You get in 1 column combined the value of a if it's there, if not you get b if it's there, if not you get c.
If you mean, that you want the information, from which table you took the index then try this:
SELECT COALESCE(table_a.index, table_b.index, table_c.index) AS firstIndexFromABC,
CASE WHEN table_a.index IS NULL AND table_b.index IS NULL THEN 'c'
WHEN table_a.index IS NULL AND table_b.index IS NOT NULL THEN 'b'
WHEN table_a.index IS NOT NULL THEN 'a'
END AS whichTable
FROM
table_a
LEFT JOIN table_b ON table_a.index = table_b.index
LEFT JOIN table_c ON table_b.index = table_c.index

INNER and LEFT OUTER join help

Say I have 3 tables. TableA, TableB, TableC
I need to operate the recordset that is available after a INNER JOIN.
Set 1 -> TableA INNER JOIN TableB
Set 2 -> TableC INNER JOIN TableB
I need the Set 1 irrespective of if Set 2 is empty or not (LEFT OUTER JOIN) comes to mind.
So essentially, I am trying to write a query and have come this far
SELECT *
FROM TableA
INNER JOIN TableB ON ...
LEFT OUTER JOIN (TableC INNER JOIN TableB)
How would I write in SQL Server?
EDIT: In reality, what I am trying to do is to join multiple tables. How would your response change if I need to join multiple tables ex: OUTER JOIN OF (INNER JOIN of TableA and TableB) and (INNER JOIN OF TableC and TableD) NOTE: There is a new TableD in the equation
SELECT * FROM TableA
INNER JOIN TableB ON TableB.id = TableA.id
LEFT JOIN TABLEC ON TABLEC.id = TABLEB.id
I Don't know what columns you are trying to use but it is just that easy
Edit:
Looking at your edit it seems that you are confused about what Joins actually do. In the example I have written above you will recieve the following results.
Columns -> You will get all of the columns for TableA,TableB and TableC
Rows-> You will start off with all of the rows from tableA. Next you will remove all rows from TableA that do not have a matching "id" in Table B.(You will have duplicates if it is not a 1:1 relationship between TableA and TableB).
Now if you take the results from above you will match any records from TableC that match the TableB.id column. Any rows from above that do not have a matching TableC record will get a null value for all of the columns from TableC in the results.
ADVICE- I am betting that only part of this made sense to you but my advice is that you start writing some queries, predict the results and then see if your predictions are correct to see if you understand what it is doing.
What you want isn't a JOIN but a UNION.
SELECT * FROM TableA INNER JOIN TableB ON ...
UNION
SELECT * FROM TableC INNER JOIN TableD ON ...
You can actually add an ordering to your joins just like in a math equation where you might do this: (5 + 4) * (3 + 1).
Given the second part of your question, give this a try:
SELECT
<your columns>
FROM
(TableA INNER JOIN Table B ON <join criteria for A to B>)
LEFT OUTER JOIN
(TableC INNER JOIN Table D ON <join criteria for C to D>) ON
<join criteria for AxB to CxD>
Select * from ((((TableA a inner join TableB b on a.id = b.id)
left outer join TableC c on b.id = c.id)
full outer join TableD d on c.id = d.id)
right outer join TableE e on e.id = d.id)
/* etc, etc... */
You can lose the brackets if you want.
try this..
SELECT *
FROM TableA a
INNER JOIN TableB b ON a.id=b.id
LEFT OUTER JOIN (SELECT *
FROM TableC c
INNER JOIN TableD d on c.id=d.id
) dt on b.id=dt.id
You didn't give your join conditions or explain how the tables are intended to be related, so it's not obvious how this might be simplified.
SELECT a.a_id, b1.b_id b1_id, b2_id, bc.c_id
FROM TableA a JOIN TableB b1 on a.b_id = b1.b_id
LEFT JOIN (SELECT c.c_id, b2.b_id b2_id
FROM TableC c JOIN TableB b2 ON c.b_id = b2.b_id
) bc ON bc.c_id = a.c_id;
Looking at your latest edit, you can do something along the lines of:
SELECT <columns>
FROM (SELECT <columns> FROM TableA JOIN TableB ON <A-B join conditions>)
LEFT JOIN
(SELECT <columns> FROM TableC JOIN TableD ON <C-D join conditions>)
ON <AB-CD join conditions>
Although you don't actually need the inner projections, and can do:
SELECT <columns>
FROM (TableA a JOIN TableB b ON <A-B join conditions>)
LEFT JOIN
(TableC c JOIN TableD d ON <C-D join conditions>)
ON <AB-CD join conditions>
Where the AB-CD join conditions are written in terms of columns of a, b, c, d etc directly.
Since you're using Sql Server, why not create views that help you? Stuffing everything in a gigantic Sql statement can become hard to read. An example view might look like:
create view AandB
as
select *
from A
inner join B on B.aid = A.aid
And the same for CandD. Then you can retrieve the optional join with simple Sql:
select *
from AndB
left outer join CandD on AndB.cid = CandD.cid
If you're interested in rows from both sets, you can do a full join:
select *
from AndB
full outer join CandD on AndB.cid = CandD.cid
Assuming I Understand your question, I think this is what you're asking for:
SELECT *
FROM TableA INNER JOIN TableB on TableA.JoinColumn = TableB.JoinColumn
LEFT OUTER JOIN TableC on TableB.JoinColum = TableC.JoinColumn
INNER JOIN TableD on TableC.JoinColumn = TableD.JoinColumn
Note that the JoinColumn used to join A & B doesn't necesarilly have to be the same column as the one used to join B & C, and so on for C & D.
SELECT *
FROM TableA A
INNER JOIN TableB B ON B.?? = A.?? AND ...
LEFT JOIN TableC C ON C.?? = B.?? AND ...
LEFT JOIN TableB B2 ON B2.?? = C.?? AND ...
LEFT JOIN TableD D ON D.?? = C.?? AND ...
So here's the thing: logically, joins aren't actually between specific tables, they are between a table and the rest of the "set" (of joins and tables). So while you know that there is a 1-to-1 relationship between C and B2 or between C and D, you can't INNER JOIN to C because C could be null from it's LEFT JOIN to B, which will eliminate those rows, effectively undoing your LEFT join.
So basically, any joins to a table that's LEFT outer joined must also be LEFT outer joined. Does this make sense?