My query join from more than 2 TABLES return double values using same key reference - sql

I'm trying to join more than 2 tables using 1 same key reference,
it works fine when I join two 2 tables using left join like this :
SELECT userProfile.UserProfileID, userProfile.name, jobPosition.levelname
FROM master.eliUserProfile userProfile
LEFT JOIN master.eliJobPosition jobPosition ON userProfile.UserProfileId = jobPosition.UserProfileID
where userProfile.UserProfileId = '5001'
Result :
userProfileid | name | levelName |
-----------------+---------+--------------+
5001 | dirdple | Direktur PLE |
5001 | dirdple | Direktur PLE |
But when I want to join another table into it, it return double values, I am using the master table reference (which is UserProfile) :
SELECT userProfile.UserProfileID, userProfile.name, jobPosition.levelname, userAcmMapping.UserAcmMappingId, userAcmMapping.RefID
FROM master.eliUserProfile userProfile
LEFT JOIN master.eliJobPosition jobPosition
ON userProfile.UserProfileId = jobPosition.UserProfileID
LEFT JOIN transactions.eliUserAcmMapping userAcmMapping
ON userProfile.UserProfileId = userAcmMapping.UserProfileID
where userProfile.UserProfileId = '5001'
and it turned out to resulted like this :
userProfileId | name | levelName | UserAcmMappingId | refId |
-----------------+---------+--------------+------------------+-------+
5001 | dirdple | Direktur PLE | 1 | 21 |
5001 | dirdple | Direktur PLE | 7 | 22 |
5001 | dirdple | Direktur PLE | 158 | 23 |
5001 | dirdple | Direktur PLE | 1 | 21 |
5001 | dirdple | Direktur PLE | 7 | 22 |
5001 | dirdple | Direktur PLE | 158 | 23 |
Is it because Iam using the same key(userProfile.UserProfileId)? Fyi, the 3rd table (userAcmMapping) have 3 values with UserProfileId=5001 and 2nd table (jobPosition) have 2 values with UserProfileId=5001.
And the table I want to be referenced is the second table with 2 values (userProfileId=5001)..
Thank you for any help..

It is because you are joining two different tables to one table with the same key. You are joining jobPositions and userAcmMapping to userProfile. I mean there are two joins on one table with the same field, so the result is doubled.
You should instead join jobPositions to userProfile and join userAcmMapping to jobPositions, like this:
SELECT userProfile.UserProfileID, userProfile.name, jobPosition.levelname, userAcmMapping.UserAcmMappingId, userAcmMapping.RefID
FROM master.eliUserProfile userProfile
LEFT JOIN master.eliJobPosition jobPosition
ON userProfile.UserProfileId = jobPosition.UserProfileID
LEFT JOIN transactions.eliUserAcmMapping userAcmMapping
ON jobPosition.UserProfileID = userAcmMapping.UserProfileID
where userProfile.UserProfileId = '5001'
Here it is one join per table.
Note: I didn't test the code, since I don't have actual tables, but it should work.

Related

How to join multiple columns in one table to another lookup table?

I am unable to figure out how to join a couple of tables together when multiple columns in one table refer to another table.
For example, I have a "document_statuses" table:
document_statuses table:
+-----------+-------------+
| status_id | status_name |
+-----------+-------------+
| 1 | RECEIVED |
| 2 | MISSING |
| 3 | NOT_NEEDED |
+-----------+-------------+
Now in another table, I am tracking the status of multiple documents:
filings table:
+-----------+-------------+----------------+----------------+----------------+
| filing_id | filing_name | doc1_status_id | doc2_status_id | doc3_status_id |
+-----------+-------------+----------------+----------------+----------------+
| 1 | John | 1 | 3 | 2 |
| 2 | Mikaela | 2 | 3 | 2 |
| 3 | Sam | 1 | 2 | 1 |
+-----------+-------------+----------------+----------------+----------------+
How would I write a query that pulls the status_name in for each column and produce the following result:
+-------------+-------------+-------------+------------+
| Filing Name | Doc1 Status | Doc2 Status | Doc3Status |
+-------------+-------------+-------------+------------+
| John | RECEIVED | NOT_NEEDED | MISSING |
| Mikaela | MISSING | NOT_NEEDED | MISSING |
| Sam | RECEIVED | MISSING | RECEIVED |
+-------------+-------------+-------------+------------+
I'm aware of how to do this when looking up a single field from document_statuses per row, but not multiple. If I only had one column in documents that referred to document_statuses, I'd do a simple JOIN:
SELECT filing_name, status_name
FROM documents d
LEFT JOIN document_statuses ds ON d.doc1_status = ds.status_id
But how do I do that when I need more than one?
You will need to join the statuses table multiple times and then alias the columns in the select clause to be formatted to be what you want. Please note that you have to alias the tables in the join clause so that you can reference the columns in the select clause of the statement.
SELECT filing_name
, ds1.status_name AS 'Doc1 Status'
, ds2.status_name AS 'Doc2 Status'
, ds3.status_name AS 'Doc3 Status'
FROM documents d
LEFT JOIN document_statuses ds1 ON d.doc1_status = ds1.status_id
LEFT JOIN document_statuses ds2 ON d.doc2_status = ds2.status_id
LEFT JOIN document_statuses ds3 ON d.doc3_status = ds3.status_id
You'll need to do three times joins with same table using different aliases for table.
SELECT filing_name, ds.status_name, ds1.status_name,
ds2.status_name FROM documents d
LEFT JOIN document_statuses ds ON d.doc1_status
LEFT JOIN document_statuses ds1 ON d.doc1_status
LEFT JOIN document_statuses ds2 ON d.doc1_status
You can do this:
select t1.filing_name, t2.status_name as doc1_status, t3.status_name as doc2_status, t4.status_name as doc3_status
from filings_table t1
inner join statuses_table t2 on t1.doc1_status_id = t2.status_id
inner join statuses_table t3 on t1.doc2_status_id = t3.status_id
inner join statuses_table t4 on t1.doc3_status_id = t4.status_id

SQL Query manipulation

I have three tables :
BookingNode , Booking AirTrip
AirTrip :
+----+------------+
| ID | Name |
+----+------------+
| 0 | One way |
| 1 | Round trip |
| 2 | Circle |
| 3 | Other |
+----+------------+
When ever we make a booking we store the data as :
BookingNode table
+--------+-------------------+------------+----------------------+
| ID | CustomerGivenName | IPAddress | Email |
+--------+-------------------+------------+----------------------+
| 177022 | xfghfh | 2130706473 | mikehussey#gmail.com |
| 177021 | cfggjfj | 2130706473 | mikehussey#gmail.com |
+--------+-------------------+------------+----------------------+
Booking Table :
+--------+---------------+-----------+------------+------------+
| ID | BookingNodeID | AirTripID | AirLineId | Provider |
+--------+---------------+-----------+------------+------------+
| 181251 | 177020 | 1 | 978 | Jet |
| 181252 | 177021 | 0 | 982 | Go |
| 181253 | 177021 | 0 | 978 | Jet |
+--------+---------------+-----------+------------+------------+
If round trip flight is booked and ProviderID is same then a single entry is done in Booking Table with AirTripID value as 1.(Booking ID : 181251 and Provider Jet )
But if providers are different for both the legs then two entries are done in Booking Table with AirTripID for both entries are one(Booking ID : 181252 and 181253 Provider Go,Jet ).In this case BookingNodeID value being same.
Prob : I have to write a query to get different type of Bookings.(Oneway, RoundTrip,Circle).But when I apply join on AirTripID , it is giving me incorrect results.
How can I write my query to give correct results knowing that BookingNodeID is going to be the same for roundtrip (both entries in Booking Table)
Sample Output
+-------------+---------------+-------------------+------------+
| AirTripName | BookingNodeID | CustomerGivenName | IPAddress |
+-------------+---------------+-------------------+------------+
| TwoWay | 177020 | xfghfh | 2130706473 |
| TwoWay | 177021 | cfggjfj | 2130706473 |
+-------------+---------------+-------------------+------------+
Basically, this code might have an error due to my laziness syntom of data entry. But, the logic of the query is, if b.AirTripID is 0, add extra condition which group by Booking. if result return more than 1 row, is actually 2 way. so AirTripType will become 1, otherwise, remain the same as b.AirTripID. You may copy below on and try fix if theres any error. i believe the logic should work based on your expected result.
select
bd.ID,
bd.CustomerGivenName,
case b.AirTripID
when 1 then 1
when 2 then 2
when 3 then 3
when 0 then
case select BookingNodeID
from Booking
where Booking.BookingNodeID = bd.ID group by BookingNodeID having Count(BookingNodeID)
when 1 then 1
else 0 end as AirTripType,
bd.IPAddress
from BookingNode bd
inner join (select BookingNodeID ,AirTripID from Booking group by BookingNodeID ,AirTripID) as b on b.BookingNodeID = bd.ID
where id=177021
Try This
WITH CTE
AS
(
SELECT
SeqNo = ROW_NUMBER() OVER(PARTITION BY BN.ID ORDER BY B.ID),
B.BookingNodeID,
BN.CustomerGivenName,
BN.IPAddress,
AirTripId = A.ID,
AirTripNm = A.Name
FROM Booking B
INNER JOIN AirTrip A
ON A.ID = B.AirTripID
LEFT JOIN BookingNode BN
ON B.BookingNodeID = BN.id
)
SELECT
C1.SeqNo,
AirTripName = CASE WHEN C2.SeqNo IS NOT NULL
THEN 'Round trip'
ELSE C1.AirTripNm END,
C1.BookingNodeID,
C1.CustomerGivenName,
C1.IPAddress
FROM CTE C1
LEFT JOIN CTE C2
ON C1.BookingNodeID = C2.BookingNodeID
AND C2.SeqNo = 2
WHERE c1.SeqNo = 1
SQL Fiddle Link Here
Select distinct bk.bookingnodeid,cst.customername,ipaddress,
case when count(airtripid)over(partition by bookingnodeid order by bookingnodeid)=2 then 'RoundTrip' else name end As AirTripName
from booking bk
inner join airlinetrip at
on bk.airtripid=at.id
inner join customer cst
on cst.id=bk.bookingnodeid

Use JOIN on multiple columns multiple times

I am trying to figure out the best way to use a JOIN in MSSQL in order to do the following:
I have two tables. One table contains technician IDs and an example of one data set would be as follows:
+--------+---------+---------+---------+---------+
| tagid | techBid | techPid | techFid | techMid |
+--------+---------+---------+---------+---------+
| 1-1001 | 12 | 0 | 11 | 6 |
+--------+---------+---------+---------+---------+
I have another table that stores the names of these technicians:
+------+-----------+
| TTID | SHORTNAME |
+------+-----------+
| 11 | Steven |
| 12 | Mark |
| 6 | Pierce |
+------+-----------+
If the ID of a technician in the first table is 0, there is no technician of that type for that row (types are either B, P, F, or M).
I am trying to come up with a query that will give me a result that contains all of the data from table 1 along with the shortnames from table 2 IF there is a matching ID, so the result would look something like the following:
+--------+---------+---------+---------+---------+----------------+----------------+----------------+----------------+
| tagid | techBid | techPid | techFid | techMid | techBShortName | techPShortName | techFShortName | techMShortName |
+--------+---------+---------+---------+---------+----------------+----------------+----------------+----------------+
| 1-1001 | 12 | 0 | 11 | 6 | Mark | NULL | Steven | Pierce |
+--------+---------+---------+---------+---------+----------------+----------------+----------------+----------------+
I am trying to use a JOIN to do this, but I cannot figure out how to join on multiple columns multiple times to where it would look something like
Select table1.tagid, table1.techBid, table1.techPid, table1.techFid, table1.techMid, table2.shortname
FROM table1
INNER JOIN table2 on //Dont know what to put here
You need to use left joins like this:
Select table1.tagid, table1.techBid, table1.techPid, table1.techFid, table1.techMid,
t2b.shortname, t2p.shortname, t2f.shortname, t2m.shortname,
FROM table1
LEFT JOIN table2 t2b on table1.techBid = t2b.ttid
LEFT JOIN table2 t2p on table1.techPid = t2p.ttid
LEFT JOIN table2 t2f on table1.techFid = t2f.ttid
LEFT JOIN table2 t2m on table1.techMid = t2m.ttid
you just do mutiple left join
select tech.techPid, techPname.SHORTNAME
, tech.techFid, techFname.SHORTNAME
from tech
left join techName as techPname
on tech.techPid = techPname.TTID
left join techName as techFname
on tech.techFid = techFname.TTID

How to create view with multiple joins on same table

In my database I have these two tables:
Person
+----+---------+---------+
| pk | name | sirname |
+----+---------+---------+
| 1 | john | leno |
| 2 | william | wallice |
| 3 | eva | apple |
| 4 | walter | white |
+----+---------+---------+
Request
+----+-------------+----------+---------------+---------+---------+
| pk | requestdate | accepted | requestperson | parent1 | parent2 |
+----+-------------+----------+---------------+---------+---------+
| 1 | 1/1/2014 | Y | 1 | 2 | 3 |
| 2 | 1/2/2014 | N | 4 | NULL | NULL |
+----+-------------+----------+---------------+---------+---------+
To get the requests I do:
SELECT *
FROM request
LEFT JOIN person p_subject ON requestperson = p_subject.pk
LEFT JOIN person p_parent1 ON parent1 = p_parent1.pk
LEFT JOIN person p_parent2 ON parent2 = p_parent2.pk
This works perfect but when I want to create a VIEW:
CREATE VIEW v_request AS
SELECT *
FROM request
LEFT JOIN person p_subject ON requestperson = p_subject.pk
LEFT JOIN person p_parent1 ON parent1 = p_parent1.pk
LEFT JOIN person p_parent2 ON parent2 = p_parent2.pk
I get this error: ORA-00957: duplicate column name
I do not want to rename all columns manually. How can I fix this?
Your view would consist of:
three columns with the columnname pk
three columns with the columnname name (which is not a good columnname)
three columns with the columnname sirname
because the tablealiases will not be prepended automatically (which the error ORA-00957: duplicate column name states exactly)
I am quite sure you will have to rename them manually to subject_pk, subject_name, subject_sirname and so on.

Using Left join sql query

I'm trying to retrieve DBName, DBNo, DBAmount, DBCountedAmount from Table A and include NewFormNo from Table B so I did this
Table A
|DBName |DBNo | DBAmount | DBCountedAmount |
|-------|--------|----------|---------------------|
|Derek |503456 | 2000 | 2000 |
|John |554422 | 40000 | 4000 |
Table B
|DBName |DBNo | DBAmount | DBCountedAmount | FormNo|
|-------|--------|----------|---------------------|-------|
|Derek |503456 | 2000 | 2000 |00001 |
|John |554422 | 40000 | 4000 |00002 |
So I did this , but it doesnt return the row I want
SELECT A.DBName,A.DBNo,A.DBAmount,A.DBCountedAmount,B.FormNo FROM Table A LEFT JOIN Table B ON A.DBNo=B.DBNo AND A.DBNo= '503456'
I want to retrieve this
|DBName |DBNo | DBAmount | DBCountedAmount | FormNo|
|-------|--------|----------|---------------------|-------|
|Derek |503456 | 2000 | 2000 |00001 |
Change this
AND A.DBNo= '503456'
to this
WHERE A.DBNo= '503456'
Also, what is the type of DBNo? If it's numeric, you can remove the ''
try this :
SELECT A.DBName, A.DBNo, A.DBAmount, A.DBCountedAmount
FROM Table A
LEFT JOIN Table B ON A.DBNo=B.DBNo
WHERE A.DBNo= '503456'
As per your question there is no need of left outer join. You can directly get by using inner join like this:
SELECT distinct a.DBname, a.DBno, a.Dbamount, a.Dbamountcount, b.FormNo
FROM tableA a inner join tableB b
on a.DBno = b.DBno
and a.DBno = 503456