Left/right join to receive all rows - sql

How can I join two tables together to get all rows from each, and enter NULL, where one is missing in the other one.
For example:
declare #t1 table (x int)
declare #t2 table (x int)
insert into #t1 select 2
insert into #t1 select 3
insert into #t1 select 4
insert into #t1 select 5
insert into #t2 select 1
insert into #t2 select 2
insert into #t2 select 5
select *
from #t1 t1
left join #t2 t2 on t2.x = t1.x
The result should look like this:
t1.x t2.x
NULL 1
2 2
3 NULL
4 NULL
5 5

select *
from #t1 t1
full outer join #t2 t2 on t2.x = t1.x
this is like left join, but will take all the records from both table even when there is no match, and will enter null when there is no match.

select *
from #t1 t1
FULL OUTER join #t2 t2 on t2.x = t1.x

All rows from both tables are returned in a full outer join. SQL Server uses the following ISO keywords for outer joins specified in a FROM clause: LEFT OUTER JOIN or LEFT JOIN. RIGHT OUTER JOIN or RIGHT JOIN. FULL OUTER JOIN or FULL JOIN

Related

Get all records using join

I have two tables like the following:
Table1
Id Table1_Col
1 A
2 B
3 C
4 D
5 E
Table2
Id Table1_Col Table2_Col
1 A Test
I want the count of (Table1_Col) in Table2 and I need query for the following output:
Expected Output
Table1_Col Count_Table2_Col
A 1
B 0
C 0
D 0
E 0
What I have tried so far:
select Table1_Col,Count(Table2_Col) from table1 t1
Left outer join table2 t2 on t1.Table1_Col = t2.Table1_Col
Please provide me a proper solution for this.
You need GROUP BY, when using aggregate methods. Also Table1_Col existing in both tables, so please use with the proper table alias for the columns.
The query below will return your expected result. Please find the demo too.
select T1.Table1_Col, Count(T2.Table2_Col) AS Table2_Col
from table1 t1
Left outer join table2 t2 on t1.Table1_Col = t2.Table1_Col
GROUP BY T1.Table1_Col
Demo on db<>fiddle
UPDATE: As per the comment in the post, based on your fiddle, the condition t3.visitno=1 should be in the LEFT OUTER JOIN and not in the WHERE clause, so the following query will work:
select t3.pvisitno, t1.DocName, count(t2.vdocid) as [count]
from Document_type t1
left outer join visitdocs t2 on t2.DocId = t1.DocId
left outer join visittbl t3 on t3.visitno = t2.visitno and t3.visitno=1
group by t3.pvisitno,t1.DocName
order by count(t2.vdocid) desc
db<>fiddle demo for the revised fiddle
Try this query:
select t1.Table1_Col,
sum(case when Table2_Col is null then 0 else 1 end) Count_Table2_Col
from Table1_Col t1
left join Table2 t2 on t1.Table1_Col = t2.Table1_Col
group by t1.Table1_Col
You can try this:
Declare #t table ( id int ,col varchar(50))
insert into #t values (1,'A')
insert into #t values (2,'B')
insert into #t values (3,'C')
Declare #t1 table ( id int ,col varchar(50),col2 varchar(50))
insert into #t1 values (1,'A','TEST')
select t.col,count(t1.id) countT2 from #t t left join #t1 t1
on t.id=t1.id
group by t.col
Here's another option:
select t1.Table1_Col, coalesce(x.cnt, 0) cnt
from table1 t1
left outer join (select Table2_Col, count(*) cnt from table2 group by Table2_Col) x
on x.Table2_Col = t1.Table1_Col;
The idea here is to create an inline view of table2 with its counts and then left join that with the original table.
The "coalesce" is necessary because the inline view will only have records for the rows in table2, so any gaps would be "null" in the query, while you specified you want "0".

Oracle - inner and left join

create table t1 (v varchar2(500), n number);
Insert into T1 (V,N) values ('a',1);
Insert into T1 (V,N) values ('bb',2);
Insert into T1 (V,N) values ('c',3);
Insert into T1 (V,N) values ('d',4);
create table t2 (v varchar2(500), n number);
Insert into T2 (V,N) values ('a',1);
Insert into T2 (V,N) values ('bb',2);
select * from t1 join t2 on t1.v = t2.v
union all
select * from t1 LEFT join t2 on t1.v = t2.v ;
Output:
a 1 a 1
bb 2 bb 2
a 1 a 1
bb 2 bb 2
d 4 (null) (null)
c 3 (null) (null)
Can we get the same above output from single scan of T1 and T2 ie from single query without UNION ALL etc? Want to re-write the above Select query so that it scans the tables T1 and T2 only once and give the same result. See the LEFT join.
The output cant be changed as we are passing it further in the application, duplicate data is required as per the requirement.
" Want to re-write the above Select query so that it scans the tables T1 and T2 only once"
You could use subquery factoring . The WITH clauses read each table once and the UNION-ed queries read from them:
with cte1 as ( select * from t1 )
, cte2 as ( select * from t2 )
select * from cte1 join cte2 on cte1.v = cte2.v
union all
select * from cte1 LEFT join cte2 on cte1.v = cte2.v ;
Here is a SQL Fiddle demo.
You can avoid excess joins and unions by doubling the rows:
select t1.*,t2.* from t1
left join t2 on t1.v=t2.v
cross join (select 1 as dbl from dual
union select 2 as dbl from dual) dbl
where dbl=1 or t2.v is not null

Joining tables in SQL if table value is equal to another

I have 3 tables. They all represent a different stage of a process.
Table1:
ID Process1
1 a
2 b
3 c
4 d
Table 2:
ID ID2 Process2
1 50 e
2 51 f
4 52 g
Table 3:
IDfromPrevious ID3 Process3
50 500 h
51 501 i
52 502 j
3 503 k
I want to create Table 4:
ID3 Process1 Process2 Process3
500 a e h
501 b f i
502 d g j
503 c k
The problem is some item move from process 1 to 3. Other items move from process 1 to 2 to 3. Everything however ends up at Process 3. The item also get assigned a new ID through each process. I am work in ms access 2016.
I don't know where to start with the SQL statement. I've never written if statements in SQL but I want the logic to work something like this:
SELECT Table3.ID3, Table1.Process1, Table2.Process2, Table3.Process3
FROM (IF Table1.ID = Table3.IDfromPrevious Then Table1 INNER JOIN Table3 ON Table1.ID = Table3.IDfromPervious ELSE Table2.ID2 = Table3.IDfromPrevious Then Table2 INNER JOIN Table3 ON Table2.ID2 = Table3.IDfromPervious)
DECLARE #Table1 TABLE
(
ID INT
,Process1 VARCHAR(10)
)
INSERT INTO #Table1
VALUES
(1,'a')
,(2,'b')
,(3,'c')
,(4,'d')
DECLARE #Table2 TABLE
(
ID INT
,ID2 INT
,Process2 VARCHAR(10)
)
INSERT INTO #Table2
VALUES
(1,50,'e')
,(2,51,'f')
,(4,52,'g')
DECLARE #Table3 TABLE
(
IDfromPrevious INT
,ID3 INT
,Process3 VARCHAR(10)
)
INSERT INTO #Table3
VALUES
(50,500,'h')
,(51,501,'i')
,(52,502,'j')
,(3,503,'k')
SELECT * FROM #Table1
SELECT * FROM #Table2
SELECT * FROM #Table3
SELECT
ID3
,Process1
,Process2
,Process3
FROM #Table1 T1
LEFT JOIN #Table2 T2 ON T1.ID = T2.ID
LEFT JOIN #Table3 T3 ON T3.IDfromPrevious IN (T2.ID2,T1.ID)
do it the simple way, join both conditions and then keep the not NULL
select t3.ID3, isnull(t1.process1, tx.Process1) Process1, t2.Process2, t3.Process3
from t3
left join t2 on t3.IDfromPrevious = t2.ID2
left join t1 on t2.ID = t1.ID
left join t1 tx on t3.IDfromPrevious = tx.ID
MS Access is only supports a subset of standard ISO SQL. After several attempts it seems this is only possible via a subquery. That subquery can then be outer joined with an Nz condition as follows:
SELECT Table3.ID3, Table12.Process1, Table12.Process2, Table3.Process3
FROM (SELECT Table2.ID2, Table1.ID, Table1.Process1, Table2.Process2
FROM Table1
LEFT JOIN Table2 ON Table2.ID = Table1.ID) AS Table12
LEFT JOIN Table3 ON Table3.IDfromPrevious = Nz(Table12.ID2, Table12.ID)

Get all records from Table When no records in Mapping Table

I have two tables in join. Here i have to get mapped records when the Second table has set of records. But when the Second table has no record i need all records from first table.
Create Table #temp1
(Id1 int)
Create Table #temp2
(Id2 int)
Insert into #temp1 Values(1),(2),(3),(4)
Insert into #temp2 Values(1),(2)
Select * from #temp1 A
Inner Join #temp2 B On A.Id1=B.Id2
It gives correct output when i have records in second table.
But when i have no records in second table i need to get all records from first table.
Delete #temp2
Select * from #temp1 A
Inner Join #temp2 B On A.Id1=B.Id2
this query return no records i tried with Left Outer Join it give all records but i am not getting records like first scenario.
Drop Table #temp1
Drop Table #temp2
I need output like this.
Thanks in Advance.
if question is not clear ,please ask me.
If you only want columns from the first table:
select a.*
from #temp1 a
where exists (select 1 from #temp2 b where b.id2 = a.id1) or
not exists (select 1 from #temp2 b);
If you wanted the extra columns from the second table, you could use union all:
Select a.*, b.*
from #temp1 a Inner Join
#temp2 b
On a.Id1 = b.Id2
union all
select a.*, b.*
from #temp1 a left join
#temp2 b
on a.id1 = b.id2
where not exists (select 1 from #temp2);
Actually you can use an OUTER JOIN:
SELECT Id1 FROM #temp1 t1
LEFT OUTER JOIN #temp2 t2
ON t1.Id1 = t2.Id2
Left join seems to work fine:
Select a.id1
from #temp1 A
left Join #temp2 B On A.Id1=B.Id2
Demo here

How to get data from three or more tables

I need to display distinct data between three tables. How to do this requirement.
FirstTable:
9999999999
8888888888
7777777777
6666666666
5555555555
SecondTable:
7777777777
9999999999
ThirdTable:
8888888888
i want output in this format.
6666666666
5555555555
Use LEFT JOIN
SELECT T1."Col"
FROM Table1 T1
LEFT JOIN Table2 T2
ON T1."Col" = T2."Col"
LEFT JOIN Table3 T3
ON T1."Col" = T3."Col"
WHERE T2."Col" IS NULL
AND T3."Col" IS NULL
Output:
| COL |
--------------
| 6666666666 |
| 5555555555 |
See this SQLFiddle
For the data you gave us, you can try this:
select YourColumn from Table1
minus
select Yourcolumn from Table2
minus
select YourColumn from Table3
This however wouldn't give you entries that existed in Table 3 but not tables 1 ND 2. I second the suggestion that you improve the question.
try this...
Select yourColumn
from Table1
where yourColumn not in
( select yourColumn from Table2)
and yourColumn not in
(select yourColumn from table3)
Try:
SELECT Column FROM FirstTable
WHERE Column NOT IN
(SELECT Column from SecondTable UNION
SELECT Column from ThirdTable)
YOUR result doesn't show distinct data. It shows the data which is not IN on any OTHER table
So you can write like this
CREATE TABLE FirstTable (VALUE VARCHAR(10))
CREATE TABLE SecondTable (VALUE VARCHAR(10))
CREATE TABLE ThirdTable (VALUE VARCHAR(10))
INSERT INTO FirstTable VALUES(9999999999)
INSERT INTO FirstTable VALUES(8888888888)
INSERT INTO FirstTable VALUES(7777777777)
INSERT INTO FirstTable VALUES(6666666666)
INSERT INTO FirstTable VALUES(5555555555)
INSERT INTO SecondTable VALUES(9999999999)
INSERT INTO SecondTable VALUES(7777777777)
INSERT INTO ThirdTable VALUES(8888888888)
SELECT a1.vALUE FROM (SELECT a.vALUE FROM FirstTable a
LEFT OUTER JOIN SecondTable b ON A.VALUE=B.VALUE
WHERE b.VALUE IS NULL) a1
LEFT OUTER JOIN ThirdTable c ON A1.VALUE=C.VALUE
WHERE c.VALUE IS NULL
Contrary to popular inclination, I think this is a good question!
The following solution finds all unique values in three tables:
with middle_tab as(
select t1.id t1_id,t2.id t2_id,t3.id t3_id from tab1 t1
full outer join tab2 t2 on t1.id=t2.id
full outer join tab3 t3 on t1.id=t3.id
)
select coalesce(t1_id,t2_id,t3_id) unique_ids from (
select t1_id,t2_id,t3_id,NVL2(t1_id,0,1)+NVL2(t2_id,0,1)+NVL2(t3_id,0,1) b
from middle_tab)
where b>1
Here is SQL Fiddle Demo!