joining two or more tables in sql - sql

I have three tables like I describe below:
TransactionHeader
ID | ProcessID | BillingHeaderID
1 1 1
2 2 2
TransactionDetail
ID | ProcessID | BillingDetailID
1 1 1
2 1 2
BillingDetail
BillingDetailID | BillingHeaderID | Amount
3 2 10000
4 2 20000
5 2 10000
6 1 10000
7 1 10000
I'm doing this so far
select
b.ID as ID_TransacHeader,
a.ID as ID_TransacDetail,
b.ProcessID
,a.BillingDetailID as Before
,c.BillingDetailID as After
from TransactionDetail a
inner join TransactionHeader b on a.ProcessID = b.ProcessID
inner join billingdetail c on b.BillingHeaderID = c.BillingHeaderID
what I'd like to get as a result something like this:
ID_TrnsacHeader | ID_TransacDetail | ProcessID | Before | After
1 1 1 1 6
1 2 1 2 7
The problem is my query above resulting something like this :
ID_TrnsacHeader | ID_TransacDetail | ProcessID | Before | After
1 1 1 1 6
1 2 1 2 6
1 1 1 1 7
1 2 1 2 7
My goal is to show difference between BillingDetailID on table TransactionDetail which is i called by "Before" and BillingDetailID on table BillingDetail which is i called by "After".
Anyone can give me a directions?
Thanks in advance

try this.......
select
b.ID as ID_TransacHeader,
a.ID as ID_TransacDetail,
b.ProcessID
,a.BillingDetailID as Before
,c.BillingDetailID as After
from TransactionDetail a
inner join TransactionHeader b on a.ProcessID = b.ProcessID
inner join billingdetail c on b.BillingHeaderID = c.BillingHeaderID and a.billingdetailid = c.billingdetailid

To join two or more tables this example might help you:
select *
from
tableA a
inner join
tableB b
on a.common = b.common
inner join
TableC c
on b.common = c.common

Related

Excluding Certain Matching Rows in an SQL Join

My issue somewhat complex, so I will explain using simplified versions of my tables.
This is Table 1:
Value L AID OID
A 1 1
B 2 1
C 3 1
D 4 1
E 2 1
F 2 2
G 2 3
H 2 4
This is Table 2:
Value R AID OID VAR
Z 0 1 0
Y 1 1 1
X 2 1 1
W 4 1 1
V 0 2 0
U 1 2 1
T 3 2 1
I would like to join these tables such that any row in Table 1 that doesn’t have a corresponding row in Table 2 with both matching AID and OID is returned in a join to the row with a matching OID and an AID and VAR of 0. In this example it would look like this:
Value L Value R AID OID VAR
C Z 3 1 0
F V 2 2 0
H V 4 2 0
I am not certain how to tackle this. Specifically, not sure how to stop the rows that have a matching AID and OID from showing up in my join, and only having the rows that don't have that match. Any advice would be appreciated.
I think you want not exists:
select t1.*
from table1 t1
where not exists (select 1
from table2 t2
where t2.aid = t1.aid and t2.oid = t1.oid and t2.var = 0
);

Why left join returns same output as cartesian join if the column values are equal

If I have 2 tables, each table has one column only:
Table A:
col1
1
1
1
Table B:
col1
1
1
1
When I say:
select * from A left join B on a.col1 = b.col1
It has same output as :
select * from A,B (cartesian join).
Why is this?
If you add another column for clarity's sake, I think the answer becomes easier to visualise:
Table A:
ID col1
1 1
2 1
3 1
Table B:
ID col1
1 1
2 1
3 1
So your cartesian product is:
A.ID A.Col1 B.ID B.ID
1 1 1 1
1 1 2 1
1 1 3 1
2 1 1 1
2 1 2 1
2 1 3 1
3 1 1 1
3 1 2 1
3 1 3 1
Now add the predicate WHERE A.Col1 = B.Col1 and you can see that this is true for all the rows. So a left join will return the same results as a cross join.

Oracle: Joins two tables to duplicate rows for 2 table

I have 2 tables like below:
Table 1
---------
1
2
3
Table 2
--------
A
B
C
How do i join to get an output like below:
Output
---------
1 A
1 B
1 C
2 A
2 B
2 C
3 A
3 B
3 C
Use Cross join:
SELECT *
FROM Table1
CROSS JOIN Table2
You can change the order by replacing * with table fields.
Read more about Cross Join.
OR you could do this:
SELECT Table1.*,Table2.*
FROM Table2,Table1
Result:
ID NAME
1 A
1 B
1 C
2 A
2 B
2 C
3 A
3 B
3 C
You want to do a CROSS JOIN and that will give you the Cartesian product of all the rows.
See http://en.m.wikipedia.org/wiki/Join_(SQL)
select * from table 1,table 2 .
For o/p like A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3
just

Avoid repeatation of rows for every instance when joined with a table

Hi i have 3 tables and i am trying to join them to get a desire table. I have tried group by and temp tables options to get the desired table but no help. I want to avoid duplicates for every instance of a value in one table from another table.
Table 1 Customer Table:
CstId CstDetails CstType
---------- --------------- ------------
1 address 1 1
2 address 2 1
3 address 3 1
4 address 4 2
5 address 5 2
Table 2 Customer Relationship:
CstId CstGroupId
---------- ----------------
1 4 (this is same as CustomerId)
2 5 (this is same as CustomerId)
3 4 (this is same as CustomerId)
Table 3 Customer Notes:
CstId NotesId NoteTxt
----------- --------- ---------
1 1 note11
1 2 note12
1 3 note13
3 1 note31
4 1 note41
4 2 note42
4 3 note43
4 4 note44
4 5 note45
Now i want the result to be in the below format
Table result:
(NoteId) (Notetxt) (NoteId) (Notetxt)
CstId CstDetails CstGroupId CstNoteId CstNote CstGroupNoteId CstGroupNote
1 address1 4 1 note11 1 note41
1 address1 4 2 note12 2 note42
1 address1 4 3 note13 3 note43
1 address1 4 null null 4 note44
1 address1 4 null null 5 note45
But i am getting CstGroupNote repeated for all the CstNote, which i am trying to avoid.
Is there a way i could achieve this result?
Below is the code i use:
select c.cstid, c.cstdetails, cn.cstnotesid, cn.cstnotetxt
insert into temp1
from customer c
left outer join customernotes cn
on c.cstid = cn.cstid
where c.customertypeid = 1
select cr.cstid, cr.cstgroupid, cn.cstgroupnoteid, cn.cstnotetxt
insert into temp2
from customerrelationship cr
left outer join customernotes cn
on cr.cstgroupid = cn.customerid
select t1.cstid, t1.cstdetails, t1.cstnotesid, t1.cstnotetxt, t2.cstgroupnoteid, t2.cstnotetext
from temp1 t1
left outer join t2
on t1.cstid = t2.cstid
Try:
select CstId,
max(CstDetails) CstDetails,
max(CstGroupId) CstGroupId,
max(CstNoteId) CstNoteId,
max(CstNote) CstNote,
max(CstGroupNoteId) CstGroupNoteId,
max(CstGroupNote) CstGroupNote
from
(select c.CstId,
c.CstDetails,
0 CstGroupId,
n.NotesId CmbNotesId,
n.NotesId CstNoteId,
n.NoteTxt CstNote,
0 CstGroupNoteId,
'' CstGroupNote
from customer c
left outer join customernotes n on c.cstid = n.cstid
where c.customertypeid = 1
union all
select c.CstId,
c.CstDetails,
r.CstGroupId,
n.NotesId CmbNotesId,
0 CstNoteId,
'' CstNote,
n.NotesId CstGroupNoteId,
n.NoteTxt CstGroupNote
from customer c
left outer join customerrelationship r on c.cstid = r.cstid
left outer join customernotes n on r.CstGroupId = n.cstid
where c.customertypeid = 1) u
group by CstId, CmbNotesId
Use a derived table and an outer join
The trick there is the
and cn.cstnotesid = cG.cstnotesid
to link those two on one row
select c.cstid, c.cstdetails, cn.cstnotesid, cn.cstnotetxt
,cG.CstGroupId, cG.cstnotesid, cG.cstnotetxt
from customer c
join customernotes cn
on cn.cstid = c.cstid
outer join (select c.cstid, c.CstGroupId, cn.cstnotesid, cn.cstnotetxt
from customer c
join customernotes cn
on cn.cstid = c.CstGroupId) as cG
on c.cstid = cG.cstid
and cn.cstnotesid = cG.cstnotesid
order by c.cstid, cn.cstnotesid, cG.cstnotesid

Show COUNT of each possible grade for an employee, showing zero when there are no grade entries

I have only one table available. I want to show the grade and the count of the number of times an employee has that grade recorded, but it must show a 0 for the grade if there are no records for that employee. I know how to do this using left join when two tables are present, but I only have 1 table.
How is this possible?
For example:
TABLE
empID | dept | grade
1 | 11 | a
2 | 11 | a
3 | 11 | b
1 | 22 | c
2 | 22 | f
3 | 22 | d
1 | 33 | a
2 | 33 | a
3 | 33 | a
If I run SELECT grade, count(grade) from table where empID = 1 Group by grade;, for example, it ends up printing out only grades the employee got and the count. Now I want to also print out the 0s for grades the employee did not have.
i think you're asking for this?
SQL> select e.grade, count(e2.empid)
2 from (select distinct grade from e) e
3 left outer join e e2
4 on e2.grade = e.grade
5 and e2.empid = 1
6 group by e.grade
7 order by grade;
G COUNT(E2.EMPID)
- ---------------
a 2
b 0
c 1
d 0
f 0
or as you have no rows with "e" grade then if you have a lookup table called grade:
SQL> select * from grade;
G
-
a
b
c
d
e
f
SQL> select e.grade, count(e2.empid)
2 from grade emp
3 left outer join emp e2
4 on e2.grade = e.grade
5 and e2.empid = 1
6 group by e.grade
7 order by grade;
G COUNT(E2.EMPID)
- ---------------
a 2
b 0
c 1
d 0
e 0
f 0
Let's say your query to select a value is:
select value from tbl;
You can ensure a 0 is returned if there are no rows in tbl t:
select nvl(t.value, 0) value
from dual d
left join tbl t on 1=1;
Sounds like you want the NVL function. With NVL, you can conditionally return an alternate value if the value is null. See the documentation.
So, if you had the following...
SELECT fooName, fooNumber FROM foo
and these were your results
fooName, fooNumber
Blah, 1
Asdf, null
Qwer, 3
poiu, null
you could rewrite the query like this...
SELECT fooName, NVL(fooNumber, 0) FROM foo
and your results would now be...
fooName, fooNumber
Blah, 1
Asdf, 0
Qwer, 3
poiu, 0
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions105.htm