Bringing data from Multiple tabel using Left outer Join - sql

I have 4 tables , A,B,C,D.
A stores my Customer Id , B ,C D stores various details of customer.
For Eg. B stores Education ,C stores Occupation , D stores Interests.
Now a Customer may have not have entry in C ,D or It may have entry in B and D but not in C.
I want to select all the information by joing all the four tables. Customer_id is present in all the four tables. Inner join will clearly not work.
I am thinking of Left outer join. Could someone help me with the requirement.

An LEFT OUTER JOIN will only get the rows where column A:B match or B:C match, if u want to keep the values of certain rows from table C, D in blank u can first make an
LEFT OUTER JOIN WITH A and B and then make a full outer join with C and D, in that way u are going to be able to keep all the data from C and D no mather if the have or not values in it
I am thinking in somethin like this:
SELECT a.store, b.education, d.storeinterest FROM
(
SELECT * FROM A
LEFT OUTER JOIN B
ON A = B
) A
FULL OUTER JOIN C
ON A = C
FULL OUTER JOIN D
ON A= D

Something along these lines should get you started:
SELECT a.*, b.*, c.*, d.*
FROM a LEFT OUTER JOIN b on
a.customer_id = b.customer_id LEFT OUTER JOIN c
on a.customer_id = c.customer_id LEFT OUTER JOIN d
on a.customer_id = d.customer_id

Related

Pull columns from series of joins in SQL

I am kind of stuck at one problem at my job where I need to pull 2 cols from base table and 1 column from a series of joins.
Please note that, I can not provide real data so I am using dummy column/table names and there are 100s of columns in real project.
Select A.Name,B.Age, D.Sal
From A Left join B on A.iD=B.id and B.Date=CURRENT_DATE
(/* join A and B table and return distinct column which is B.XYZ)
inner join C on C.iD=B.XYZ
(/* join B and C take C.YYY column for next join */)
inner join D on D.id=C.YYY
(/* Take out the D.Sal column from this join */) where A.Dept='IT'
I have written this query but it is taking forever to run because B.XYZ column has a lot of duplicates. how can I get distinct of B.XYZ column from that join.
For Joining Table B, you first get a distinct table of the columns you need from B then join.
SELECT
A.Name,
B.Age,
D.Sal
From A
LEFT JOIN ( -- Instead of all cols (*), just id, Date, Age and xyz might do
SELECT DISTINCT * FROM B
) B ON A.iD = B.id AND B.Date = CURRENT_DATE
--(/* join A and B table and return distinct column which is B.XYZ */)
INNER JOIN C ON C.iD = B.XYZ
--(/*join B and C take C.YYY column for next join */)
INNER JOIN D ON D.id = C.YYY
--(/* Take out the D.Sal column from this join */)
WHERE A.Dept='IT'
You say you get the same rows multifold, because for a b.id, date and age you get the same xyz more than once, or so I understand it.
One option is to join with a subquery that gets the distinct data:
SELECT a.name, b.age, d.sal
FROM a
LEFT JOIN
(
SELECT DISTINCT id, date, age, xyz FROM b
) dist_b ON dist_b.id = a.id and dist_b.date = CURRENT_DATE
INNER JOIN c ON c.id = dist_b.xyz
INNER JOIN d ON d.id = c.yyy
WHERE a.dept = 'IT';
Of course you can even move the date condition inside the subquery:
SELECT a.name, b.age, d.sal
FROM a
LEFT JOIN
(
SELECT DISTINCT id, age, xyz FROM b WHERE date = CURRENT_DATE
) dist_b ON dist_b.id = a.id
INNER JOIN c ON c.id = dist_b.xyz
INNER JOIN d ON d.id = c.yyy
WHERE a.dept = 'IT';
Your LEFT OUTER JOIN doesn't work by the way. As you are inner joining the following tables, a match must exists, so your outer join becomes an inner join. For the outer join to work you would have to outer join the following tables, too.

Aggregation function with the inner join on sql server

I have 5 tables (A,B,C,D). All are inner joined and used to display data. Another table E has the column sourceId which has reference in column A. I need to show the count of occurrence in the main query. For example:
A.*,B.*,C.*,D.*
FROM A
INNER JOIN B
ON A.BId= B.Id
INNER JOIN C
ON A.CId = C.Id
INNER JOIN D
ON A.Did= D.Id
E table can contain 2 or 1 or 0 records referencing to table A. I need to display count of the occurrence in the above query and sort accordingly from 0 to 2. Can some one help me writing this up? I am not sure how should I go ahead with aggregation function over here.
Output should look like this:
E.Count|A.*|B.*|C.*|D.*|
Something like this:
select A.*,B.*,C.*,D.*,E_count
FROM A
INNER JOIN B ON A.BId= B.Id
INNER JOIN C ON A.CId = C.Id
INNER JOIN D ON A.Did= D.Id
outer apply (
select count(*) as E_count
from E
where E.sourceId = A.Id
) E
or
select A.*,B.*,C.*,D.*,E_count
FROM A
INNER JOIN B ON A.BId= B.Id
INNER JOIN C ON A.CId = C.Id
INNER JOIN D ON A.Did= D.Id
left join (
select count(*) as E_count
from E
group by E.sourceId
) E on E.sourceId = A.Id

Getting a field from a table that is not in the left outer join in the same query

I have 4 tables, 3 of which are joined, but I need to get a field from the forth table (Table_D). For the sake of simplicity lets say they are Tables A, B, C, D.
Select Distinct A.Field_1, B.Field_2, C.Field_3
From Table_A
Left outer join B on A.Field_z= B.Field_z
Left Outer Join C on A.Field_z= C.Field_z
where A.Field_z in (1111);
This seems to work but I need a field in Table_D that is only connected to Table_A through Table_C.
How can I add it to the join? or can I?
Thanks!
WB
The on clause has essentially all the features of the where clause. on clauses for any part of the join can refer to any attribute of any entity in the from clause, I suspect your confusion comes from thinking that you can only join subsequent entities to the first entity in the from clause. If Table_D is related to Table_A through Table_C, you might see a from/join/on construct like:
select a.thing, b.things, c.thang, d.stuff
from Table_A a
left join Table_B b
on a.id = b.a_id
left join Table_C c
on a.id = c.a_id
left join Table D d
on d.id = c.d_id
where
a.this = b.that
Note that the word "outer" is implied in a left join, and is not necessary for syntactic completion.
Of course you can add it. You don't specify the logic, but something like this:
Select Distinct A.Field_1, B.Field_2, C.Field_3, D.??
From Table_A a Left outer join
B
on A.Field_z= B.Field_z Left Outer Join
C
on A.Field_z= C.Field_z Left Outer Join
D
on . . .
where A.Field_z in (1111);
Just fill in the conditions that you want. You want a left join, because the condition between c and d would otherwise turn the outer join to c into an inner join.
If I understand you correctly, I believe this would work:
Left Outer Join D on C.Field_z= D.Field_z
You can try this way. It will help i guess
Select Distinct A.Field_1, B.Field_2, C.Field_3, c.Field_4
From Table_A
Left outer join B on A.Field_z= B.Field_z
Left Outer Join ( select C.field_3, d.Field_4, c.Field_z from c inner join d on c.field_z = d.field_z ) c on A.Field_z= C.Field_z
where A.Field_z in (1111);

How to show all the data in the row SQL

I want to know the query that could show me the data in a row in Inner Join table
Image
as you see from the pic that I have 4 tables in the inner join table , I want to know how to show the blue 1 in BeefId with WorWOId 1 in on table
I can show all data in table beef by using
select a.* from Tbl_Beef a
INNER JOIN Tbl_Add b ON a.Id = b.Id ;
but I don't know how to join WorWOId with it
You just make another join between Tbl_Add and Tbl_WithOrWithot
SELECT a.*
FROM Tbl_Beef a
INNER JOIN Tbl_Add b
ON a.Id = b.Id
INNER JOIN Tbl_WithOrWithot w
ON b.WorWOID = w.id
I am assuming that you are wanting tbl_withorwithot also? sorry if misunderstanding the question.
Select * From Tbl_Add a
INNER JOIN Tbl_Beef b ON a.BeefID = b.Id
INNER JOIN Tbl_WithORWithot c ON a.WorWOID = c.Id
This will only show records that exist in all 3 tables, so you can reorder and change to outer joins if you need different.
Hope that helps.

Stuck on multiple table filtering query

Ok so I will try to simplify the problem that I have.
I have 4 tables:
TableA:
OneID
TableB:
OneID (FK to TableA)
TwoID (FK to TableC)
TableC:
TwoID
ThreeID (FK to TableD)
TableD:
ThreeID
I need a query to retrieve data from all 4 of these tables.
The query criteria is:
want to inner join tables A, B, C
want to join above result with table D with the following conditions:
if a record is in Table D but not in Table C, then it must always be present in the results
otherwise if a record is in Table D and Table C, then it should only be present if it is in the result of the A,B,C join
The scenario you have described is not really possible (or at least they are not really logical)
if a record is in Table D but not in Table C, then it must always be present in the results
The only way a record could be "in Table D and not in Table C" is if the foreign key is null in table D, with no link from table D to tables A or B there is no other way you could define a record as being present in D and not in C:
otherwise if a record is in Table D and Table C, then it should only be present if it is in the result of the A,B,C join
Again, the only way this could happen is with NULLABLE foreign keys. Regardless I think any of the below will get you the results you require:
SELECT A.OneID, B.TwoID, c.ThreeID, D.FourID
FROM D
LEFT JOIN (C
INNER JOIN B
ON B.TwoID = C.TwoID
INNER JOIN A
ON A.OneID = B.OneID)
ON C.ThreeID = D.ThreeID;
Or
SELECT A.OneID, B.TwoID, c.ThreeID, D.FourID
FROM A
INNER JOIN B
ON B.OneID = A.OneID
INNER JOIN C
ON C.TwoID = B.TwoID
RIGHT JOIN D
ON D.ThreeID = C.ThreeID
Or
SELECT A.OneID, B.TwoID, c.ThreeID, D.FourID
FROM A
INNER JOIN B
ON B.OneID = A.OneID
INNER JOIN C
ON C.TwoID = B.TwoID
INNER JOIN D
ON D.ThreeID = C.ThreeID
UNION ALL
SELECT NULL, NULL, NULL, FourID
FROM D
WHERE ThreeID IS NULL;
Examples on SQL Fiddle
The first two have the same execution plan, it is just a matter of preference, I personally dislike using RIGHT JOIN because it makes queries feel like they in the wrong order i.e bottom to top, but this is purely my preference. The last query may perform better depending on the cardinality of your data and any indexes you have
EDIT
With your revised criteria I think the easiest way to implement this is with a UNION ALL:
SELECT A.OneID, B.TwoID, c.ThreeID, d3 = D.ThreeID
FROM A
INNER JOIN B
ON B.OneID = A.OneID
INNER JOIN C
ON C.TwoID = B.TwoID
INNER JOIN D
ON D.ThreeID = C.ThreeID
UNION ALL
SELECT NULL, NULL, NULL, ThreeID
FROM D
WHERE NOT EXISTS (SELECT 1 FROM C WHERE C.ThreeID = D.ThreeID);
Example on SQL Fiddle
I am not 100% sure I understood you correctly but I will try to help anyway. It seems that you need to do FULL OUTER JOIN on table D:
SELECT
*
FROM
TableA AS A INNER JOIN
TableB AS B ON B.A_Id = A.Id INNER JOIN
TableC AS C ON C.B_Id = B.Id FULL OUTER JOIN
TableD AS D ON D.C_Id = C.Id
If I have misunderstood your requirements and you need more complicated criteria, you could just do FULL OUTER JOIN on all the tables and put extra conditions in WHERE part:
SELECT
*
FROM
TableA AS A FULL OUTER JOIN
TableB AS B ON B.A_Id = A.Id FULL OUTER JOIN
TableC AS C ON C.B_Id = B.Id FULL OUTER JOIN
TableD AS D ON D.C_Id = C.Id
WHERE
--if a record is in Table D but not in Table C, then it must always be present in the results
(D.Id IS NOT NULL AND C.Id IS NULL) OR
(
--otherwise if a record is in Table D and Table C, then it should only be present if it is in the result of the A,B,C join
(D.Id IS NOT NULL AND C.Id IS NOT NULL) AND
--want to inner join tables A, B, C
(A.Id IS NOT NULL AND B.Id IS NOT NULL AND B.Id IS NOT NULL)
)