How to join two tables in this example - sql

I got a problem getting records out of two tables correctly.
I need to get a list in which every device and its software is linked.
Hard to explain what my goal is, but i hope you will understand my Example.
Example:

You need a join with multiple instances of table2
select b.name,c.name
from table1 a inner join table2 b on a.targetid=b.objectid
inner join table2 c on a.assignedid=c.objectid

JOIN the Table2 two times with Table1 and add the proper alias names will solve in your request.
The working query is:
SELECT T2.Name AS ComputerName, T3.Name AS SoftwareName
FROM Table1 T1
JOIN Table2 T2 T2.ObjectId = T1.TargetId
JOIN Table2 T3 T3.ObjectId = T1.AssignedId

Related

When to use right join or full outer join

I work with DB / SQL almost on a daily basis and the more I work with sql, the more I'm the opinion that there is no reason to use a right join or a full outer join.
Let's assume we have two tables: table1 and table2. Either I want to receive additional information for the rows in table1 so I can use an inner join on table2 and if I want to keep the original rows if there is no match, I use the left join then:
In case I have to add additional information to table 2, I can do the same and left join table 2 to table on. So I do not see a reason why I should ever use a right join. Is there any use case where you can not use a left join for a right join?
I also wondered if I would ever need a full outer join. Why would you join two tables and keep the rows that do not match of BOTH tables? We you could also achieve this by using two left joins.
Why would you join two tables and keep the rows that do not match of BOTH tables?
The full join has cases where it is useful.One of them is comparing two tables for differences like XOR between tables:
SELECT *
FROM t1
FULL JOIN t2
ON t1.id = t2.id
WHERE t1.id IS NULL
OR t2.id IS NULL;
Example:
t1.id ... t2.id
1 NULL
NULL 2
you could also achieve this by using two left joins.
Yes you could:
SELECT t1.*, t2.*
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
WHERE t2.id IS NULL
UNION ALL
SELECT t1.*, t2.*
FROM t2
LEFT JOIN t1
ON t1.id = t2.id
WHERE t1.id IS NULL;
Some SQL dialects does not support FULL OUTER JOIN and we emulate it that way.
Related: How to do a FULL OUTER JOIN in MySQL?
On the other hand RIGHT JOIN is useful when you have to join more than 2 tables:
SELECT *
FROM t1
JOIN t2
...
RIGHT JOIN t3
...
Of course you could argue that you could rewrite it to correspodning form either by changing join order or using subqueries(inline views). From developer perspective it is always good to have tools(even if you don't have to use them)

One update SQL query from three tables

I have three tables and I have to write one query to update table 1 row from table 3 and the only matching columns I have is in table 2.
Table 1 which has incorrect data:
Table 3 has the correct data:
I did try to write a query and execute it but it gives me an error saying there are too many rows too select which is true I do have many rows to correct but it still wouldn't correct. What do you think I should do. This is my query so far.
UPDATE Table1
SET Table1.Number = (SELECT Table3.Number
FROM Table2
FULL OUTER JOIN Table1 ON Table1.ID = Table2.ID
FULL OUTER JOIN Table3 ON Table3.Signin = Table2.Signin
WHERE (Table2.ID = Table1.ID)
AND (Table1.Number = 'xxx'))
WHERE (Tale1.Number = 'xxx')
In Where clause of JOIN query need to modify as multiple records are generating by inappropriate condition.Try to use Table3 components instead of using Table1 in joining query where clause.
UPDATE Table1
SET Table1.NUMBER = (SELECT table3.NUMBER FROM Table1 FULL OUTER JOIN Table2
ON Table1.ID = Table2.ID
FULL OUTER JOIN Table3
ON Table2.SIGNIN = Table3.SIGNIN
WHERE Table3.SIGNIN = 100) // This is the point where you need to modify your code
WHERE Table1.ID = 1;
ONLINE DEMO HERE
It actually worked after I removed this line from my query.
FULL OUTER JOIN Table1 ON table1.ID = Table2.ID
Thanks for the help.
You are fairly close. When doing the update though unless you are wanting to clear value for t1.number when a record is not matched in t3, you will want to use INNER JOIN. FULL OUTER JOIN would mean you are trying to update rows in t1 that don't exist but a LEFT JOIN you would update t1.number to NULL if a record in t3 doesn't exist.
UPDATE t1
SET t1.Number = t3.Number
FROM
Table1 t1
INNER JOIN Table2 t2
ON t1.Id = t2.Id
INNER JOIN Table3 t3
ON t2.Signin = t.3.Signin
WHERE
t1.number <> t3.number
--Or if you have nulls something like
--ISNULL(t1.number,'xxx') <> ISNULL(t3.number,'xxx')
-- if you only want to update when t1.number = 'xxx' then
--t1.number = 'xxx'
t1,t2,t3 are table aliases that I created by adding the alias after table name. By using join syntax rather than a sub select you simplify your were conditions. In sql-sever if more than 1 record in t2 & t3 match it will select one row randomly in the case of a one to many relationship. If you want a specific record when not one to one relation you can use window functions and common table expressions (cte) to limit t3 to the exact record you want to use.

SQL Joining three tables and using LEFT OUTER JOIN

I have three tables and two seperate SQL queries which are working correctly and I am having correct results.
If I try to join these three tables I am having null as result.
First query:
select T1.ID,T3.COMPANY
from T1,T3
where (T1.status!='CLOSED') and (T1.PRIORITY)>5 and T1.CLASSID=T3.CLASSID
Second query:
SELECT T1.ID, T2.DESCRIPTION
FROM T1
LEFT OUTER JOIN T2
ON T1.ID=T2.KEY
WHERE T1.status!='CLOSED'
AND (T2.CREATEDATE= (SELECT MAX(CREATEDATE)
FROM T2
WHERE T2.KEY=T1.ID))
I tried to join them but as result I am having null:
select T1.ID,T3.COMPANY,T2.DESCRIPTION
from T1
INNER JOIN T3 ON T1.CLASSID=T3.CLASSID
LEFT OUTER JOIN T2
ON T1.ID=T2.KEY
where (T1.status!='CLOSED') AND (T1.PRIORITY)>5
AND (T2.CREATEDATE= (SELECT MAX(CREATEDATE)
FROM T2
WHERE T2.KEY=T1.ID))
like it does not recognized last part for taking MAX value from T2 table.
What am I doing wrong? Thanks for help
Firstly, use an alias for the subquery on table T2.
T2.CREATEDATE =
(SELECT MAX(T2Alias.CREATEDATE)
FROM T2 AS T2Alias
WHERE T2Alias.KEY = T1.ID)
Secondly, consider moving this condition into the ON clause of the LEFT JOIN to table T2.
The first thing that jumps out at me is the new dependency on both T1.Priority > 5 and T2.CreateDate value being equal to the result of the inline query:
( AND (T1.PRIORITY) > 5
AND (T2.CREATEDATE =
(SELECT MAX(CREATEDATE) FROM T2 WHERE T2.KEY = T1.ID) )
Without the data it's difficult to check however this may be the issue

SQL select column when there's more than one of the same name

I have this query
select *
from alldistros t1
LEFT join origin t2 on t1.name=t2.name
LEFT join desktop t3 on t2.name=t3.name
LEFT join beginnerdistributions t4 on t3.name=t4.name
it add on all my tables. But now when I want to select the name field (which is in all of them) I can't show it. It's just blank when I call it. And I would think so since there's more than 1 columns of the same name.
What can I do to fix this?
Just a plain join won't work, since it removes some of the fields that does not have the properties in the other tables.
You can use the 'AS' keyword to name a column. For instance:
select t1.name AS DistroName, t2.name AS OriginName, t3.name AS DesktopName
from alldistros t1
LEFT join origin t2 on t1.name=t2.name
LEFT join desktop t3 on t2.name=t3.name
LEFT join beginnerdistributions t4 on t3.name=t4.name
select
t1.name as t1_name,
t2.name as t2_name,
t3.name as t3_name
from alldistros t1
LEFT join origin t2 on t1.name=t2.name
LEFT join desktop t3 on t2.name=t3.name
LEFT join beginnerdistributions t4 on t3.name=t4.name
Not sure if it's Oracle only, but USING can do this for you for ad-hoc queries:
SELECT *
FROM TABLEA
JOIN TABLEB USING (NAME)
This will only return one NAME column from the SELECT *.

Compound SQL Join?

I'm trying to construct a SQL query that I think requires multiple JOIN's, but I don't know the syntax.
Here is a rough example of the Tables (with column names) for each.
T1 (key, name)
T2 (key, fkeyT1)
T3 (key, fkeyT2)
I want to get all the rows from T3 that are linked to rows in T2 that are linked to rows in T1 with a given name.
I figure I'll need at least 2 JOIN's; I've got the first JOIN I think:
SELECT *
FROM T3 INNER JOIN T2
ON T3.fkeyT2 = T2.key
I figure I'll need to take these results and do another JOIN with T1 but I'm not sure of the syntax.
You probably want something like
SELECT *
FROM t3 INNER JOIN t2 ON (t3.fkeyT2 = t2.key)
INNER JOIN t1 ON (t2.fkeyT1 = t1.key)
WHERE t1.name = 'Foo'