SQL Multiple columns on one table joined column from other table - sql

I've been trying to run an SQL query but haven't been having much luck. No matter what I do I can't seem to get it to run the way I need it to. I am able to get the tables to join and get the names across, but I can't get the query output I'm looking for.
I have two tables, one table has 3 columns for 1st, 2nd, and 3rd gate techs to be entered. The second table has a list of gate techs we use, the ID for the techs is the primary key.
What I'm looking for is an SQL statement that will get the the keys from the gate table. Example would be Gate Table ID 2 would get 2, 2, 1, then join with the tech table and return the tech names instead of the key.
I can one to work if I do the following, but cant get 3 separate columns with the data.
SELECT TName
FROM TechTable
INNER JOIN GateTable
ON GateTabe.Gate1=TechTable.ID
WHERE ID = 3
-
GateTable
ID Gate1 Gate2 Gate3
1 1 2 3
2 2 2 1
3 4 2 1
-
TechTable
ID TName
1 Tech1
2 Tech2
3 Tech3
4 Tech4
Query Result
ID Gate1 Gate2 Gate3
1 Tech1 Tech2 Tech3
2 Tech2 Tech2 Tech1
3 Tech4 Tech2 Tech1

join the techTable thrice, once for each different gate.
SELECT g.id,t1.TName as gate1,t2.TName as gate2,t3.TName as gate3
FROM GateTable g
INNER JOIN TechTable t1 ON g.Gate1=t1.ID
INNER JOIN TechTable t2 ON g.Gate2=t2.ID
INNER JOIN TechTable t3 ON g.Gate3=t3.ID

SELECT gt.ID, t1.TName as Gate1, t2.TName as Gate2, t3.TName as Gate3
FROM GateTable gt
LEFT JOIN TechTable t1
ON gt.Gate1=t1.ID
LEFT JOIN TechTable t2
ON gt.Gate2=t2.ID
LEFT JOIN TechTable t3
ON gt.Gate3=t3.ID
You can use INNER JOIN too but it gives you only mapped columns. In your example you specified Gate1 value as 4, but it is not there in TechTable. In this case, INNER JOIN skips that value. But LEFT JOIN would give you mapped values and null for the not available mapping.
You can use where clause if you need specific GateID.

Related

SQL/Presto: right join bigger than original table due to NULL

I need to right join 2 tables with 3 conditions but the resulting table is bigger than left or right table.
left_table a is like the following:
capacity value group_id level_id tags
100 3 a ab
120 5 a afb lala
122 4 b afg hhh
122 6 c adfg
right table b is like the following: bigger than left table
user group_id level_id tags
adsf a ab
af a abf df
sf a afb lala
dsf b afg hhh
sdf c adfg
I want to append the value and capacity value to the right table b. I have used the following query but the resulting table is larger than the right table. I noticed that it is due to the NULL in tags in both the right and left tables, but i am wondering how to resolve this issue.
select a.capacity, a.value, b.*
from a
right join b
on a.group_id = b._group_id
and a.level_id = b.level_id
and a.tags = b.tags
I noticed that it is due to the NULL in tags in both the right and left tables
No, this is not the cause of duplicates. In fact NULL values fail the comparison, so you will not get a match at all if either value is NULL. That is, the row in b will be returned with NULL values for the columns from a.
If you want NULL values to match as being equal, then you need a NULL-safe comparison -- and Presto supports the SQL Standard is not distinct from. I also strongly prefer left join over right join:
select a.capacity, a.value, b.*
from b left join
a
on a.group_id = b._group_id and
a.level_id = b.level_id and
a.tags is not distinct from b.tags;
If you are getting duplicates, it is because you have duplicates in a. You can check for this using:
select group_id, level_id, tags, count(*)
from a
group by group_id, level_id, tags
having count(*) >= 2;

JOIN query, SQL Server is dropping some rows of my first table

I have two tables customer_details and address_details. I want to display customer details with their corresponding address, so I was using a LEFT JOIN, but when I'm executing this query, SQL Server drops rows where street_no of customer_details table doesn't match with the street_no in address_detials table and displays only rows where `street_no' of customer_detials = street_no of address_details table. I need to display a complete customer_details table and in case if street_no doesn't matches it should display empty string or anything. Am I doing anything wrong in my SQL join?
Table customer_details:
case_id customer_name mob_no street_no
-------------------------------------------------
1 John 242342343 4324234234234
1 Rohan 343233333 43332
1 Ankit 234234233 2342332423433
1 Suresh 234234324 2342342342342
1 Ranjeet 343424323 32233
1 Ramu 234234333 2342342342343
Table address_details:
s_no streen_no address city case_id
------------------------------------------------------
1 4324234234234 Roni road Delhi 1
2 2342332423433 Natan street Lucknow 1
3 2342342342342 Koliko road Herdoi 1
SQL JOIN query:
select
a.*, b.address
from
customer_details a
left join
address_details b on a.street_no = b.street_no
where
b.case_id = 1
Now that it became clear that you used b.case_id=1, I will explain why it filters:
The LEFT JOIN itself returns some rows that contain all NULL values for table b in the result set, which is what you want and expect.
But by using WHERE b.case_id=1, the rows containing NULL values for table b are filtered out because none of them matches the condition (all those rows have b.case_id=NULL so they don't match).
It might work to instead use WHERE a.case_id=1, but we don't know if a.case_id and b.case_id are always the same value for matching rows (they might not be; and if they are always the same, then we just identified a potential redundancy).
There are two ways to fix this for sure.
(1) Move b.case_id = 1 into the left join condition:
left join address_details b on a.street_no = b.street_no and b.case_id = 1
(2) Keep b.case_id = 1 in the WHERE but also allow for NULLED-out b values:
left join address_details b on a.street_no = b.street_no
where b.case_id = 1
or b.street_no IS NULL
Personally I'd go for (1) because that is the most clear way to express that you want to filter b on two conditions, without affecting the rows of a that are being returned.
I do think that Wilhelm Poggenpohl answer is kind of right. You just need to change the last join condition a.case_id=1 to b.case_id=1
select a.* , b.address
from customer_details a
left join address_details b on a.street_no=b.street_no
and b.case_id=1
This query will show every row from customer_details and the corresponding adress if there is a match of street_no and the adress meets the condition case_id=1.
This is because of the where clause. Try this:
select a.* , b.address
from customer_details a
left join address_details b on a.street_no=b.street_no
and a.case_id=1

Origin-Destination Table join

How to join the following tables? Or is this possible?
Column origin and destination is fk.
**tbleroute**
ID ORIGIN DESTINATION
1 1 3
2 1 2
3 3 4
**tblelocation**
ID Name
1 Bus Station
2 Market
3 Bus Station 2
4 School
For the obvious result, you need two joins. This looks like:
select r.*, lo.name as origin_name, ld.name as destination_name
from tblrouter r join
tbllocation lo
on r.origin = lo.id join
tbllocation ld
on r.destination = ld.id;
This is a situation where table aliases are needed in the from clause to distinguish the tables.

Table Join Distinct Field

The problem which I am having is joining two tables. One table contains all the generic data and the second table contains old fields which have been given specific values. The exemplary tables below should help to clarify my setup.
Table 1 (Generic Data)
ParaIndex ParaName ParaDefault
1 Cat 15
2 Fish 8
3 Dog 3
Table 2 (Specific Data)
Project ParaIndex ParaValue
John 1 6
John 2 7
Alan 3 9
The goal then is to join these tables to get a single table:
Table 3 (Table Join on ParaIndex for 'John')
ParaName ParaIndex ParaValue ParaDefault
Cat 1 6 15
Fish 2 7 8
Dog 3 3
So Table 3 would return all rows from Table 1 but would only show values for ParaValue where they are not empty. E What I have tried so far is a combination of changing the join type, distinct select, group by, select subqueries, and suggestions mentioned in other posts.
The end goal is then to use this query in vb.net as par of a form.
The closest which I have gotten is to return the requested data in table 3, but it would exclude rows which are not requested (e.g. if the query is for 'John' it would then exclude the parameters marked by 'Alan' which is 3-Dog in this case).
SELECT t1.ParaName, t1.ParaIndex, t2.ParaValue, t1.ParaDefault
FROM Table1 AS t1LEFT OUTER JOIN Table2 AS t2
ON t1.ParaIndex = t2.ParaIndex
WHERE (((t2.ParaIndex) is null) OR t2.Project = 'John')
You have to use a LEFT OUTER JOIN:
SELECT t1.ParaName,
t1.ParaIndex,
COALESCE(CAST(t2.ParaValue AS VARCHAR(10), '') AS ParaValue,
t1.ParaDefaule,
FROM dbo.Table1 t1
LEFT OUTER JOIN dbo.Table2 t2
ON t1.ParaIndex = t2.ParaIndex
WHERE t2.Project = 'John'
ORDER BY t1.ParaIndex

SQL - Left join 2 foreign keys to 1 primary key

I have two tables, Games and Teams. What should my sql statement look like to make a list of games that pulls in the TeamName that is linked to the TeamID1 and TeamID2 fields? I believe I could use a left join but I'm not sure what to do with two foreign keys that link to one primary key. Thank you very much for any help you could provide.
Games
GameID
TeamID1
TeamID2
Result
Teams
TeamID
TeamName
I often see folks struggle with the idea of joining a table unto itself or multiple times in the same query (as it were here). Once mastered, it's a great technique to use on tables that have a lot of relationships between rows (such as a list of teams that have to play each other!). As others have pointed out, you need to use two inner joins to accomplish this:
select
*
from
games g
inner join teams t1 on
g.teamid1 = t1.teamid
inner join teams t2 on
g.teamid2 = t2.teamid
So, if your games table looks like this:
GameID TeamID1 TeamID2
----------------------------
1 1 3
2 4 2
3 2 1
You will get the result set of:
g.GameID g.TeamID1 g.TeamID2 t1.TeamID t1.Name t2.TeamID t2.Name
----------------------------------------------------------------------------------
1 1 3 1 Lions 3 Bears
2 4 2 4 Oh My 2 Tigers
3 2 1 2 Tigers 1 Lions
Of course, I would alias these columns in the select statement, if I were me, for usability's sake:
select
g.GameID,
t1.Name as Team1,
t2.Name as Team2
from
...
This way, columns can be named appropriately, instead of having the t1 and t2 columns share the same names.
Now, to address the confusion about what a left join is. You see, a left join will take all of the rows from the first (or left) table, and then match up any rows on the join condition to the second (or right) table. For any rows from the left table, you will get null in all of the columns on the right table.
Delving into an example, let's say that somebody put in a null for TeamID2 on one of the rows for whatever reason. Let's also say that a team of TeamID 4 used to exist, but doesn't any more.
GameID TeamID1 TeamID2
----------------------------
1 1 3
2 4 2
3 1 null
Now, let's take a look at what a left join would be in terms of the query:
select
*
from
games g
left join teams t1 on
g.teamid1 = t1.teamid
left join teams t2 on
g.teamid2 = t2.teamid
Logically, this will grab all of our games, and then match them up to the respective teams. However, if a TeamID doesn't exist, we'll get nulls. It will look like so:
g.GameID g.TeamID1 g.TeamID2 t1.TeamID t1.Name t2.TeamID t2.Name
----------------------------------------------------------------------------------
1 1 3 1 Lions 3 Bears
2 4 2 null null 2 Tigers
3 1 null 1 Lions null null
Therefore, a left join will only be necessary if a team is optional.
In your case, you'll be using an inner join to join a table multiple times. This is a very common practice and is rather useful. It avoids some of the pitfalls of subqueries (especially on MySQL), while allowing you to grab data from the table for intratable comparisons. This is markedly useful when trying to find the order of something, or related rows.
Anyway, I hope this very rambling answer helps out somebody somewhere.
SELECT *
FROM Games G
INNER JOIN Teams T1
ON G.TeamID1 = T1.TeamID
INNER JOIN Teams T2
ON G.TeamID2 = T2.TeamID
I don't think you'll need a left outer join unless one of the two teams in a game is optional. Logically to me it seems that both would be required, so your query would look like this:
SELECT *
FROM Games AS G
INNER JOIN Teams AS T1 ON T1.TeamID = G.TeamID1
INNER JOIN Teams AS T2 ON T2.TeamID = G.TeamID2
If TeamID1 and TeamID2 are NOT NULL, then you want to use an INNER JOIN, otherwise you could use a LEFT JOIN.
You need to use alias:
SELECT GameID, team1.TeamName, team2.TeamName
FROM Games INNER JOIN teams team1 ON (Games.TeamID1 = team1.TeamID)
INNER JOIN teams team2 ON (Games.TeamID2 = team2.TeamID)