SQL - Need to conditionally join based on value in TableB column - sql

I need to know the rows in TABLE A that have join records in TABLE B based a column value in TABLE B, but I also need to return rows in which a row in TABLE A has no match in TABLE B.
It seems like I need a LEFT JOIN and a LEFT OUTER JOIN, so I'm not sure what to do there. I understand how to do each, but don't understand how to do them together.
The schema looks like:
TABLE_A
pk
TABLE_B
pk
a_fk
some_value
I need the joined rows where Table_A has no join record in Table_B OR Table_A has a join record row in Table_B (it can have many) in which some_value does not equal "thisValue"
Thanks.

A Left join is a left outer join. Outer joins preserve one of the tables which is what you are after so good guess.
SELECT *
FROM Table A
LEFT JOIN Table B
ON TableA.Column = TableB.Column
AND B.SomeValue <> 'ThisValue'
All of the rows with a match will have the B information populated all of those without will have nulls in the B data

Related

duplicate query result when join table

I face issue about duplicate data when join table, here my sample data table I have
-- Table A
I want to join with
-- Table B
this my query notation for join both table,
select a.trans_id, name
from tableA a
inner join tableB b
on a.ID_Trans = b.trans_id
and this the result, why I get the duplicating data which should show only two lines of data, please help me to solve this case.
Firstly, as you have been told multiple times in the comments, this is working exactly as you have written, and (more importantly) as intended. You have 2 rows in tableA and those 2 rows match 2 rows in your table tableB according to the ON clause. This means that each join operation, for the each of the rows in tableA, results in 2 rows as well; thus 4 rows (2 * 2 = 4).
Considering that your table, TableA only has one column then it seems that you should be cleaning up that data and deleting the duplicates. There are plenty of examples on how to do that already (example).
Perhaps the column you show us in TableA is one many, and thus instead you have a denormalisation issue, and instead there should be another table with the details of Id_trans and a PRIMARY KEY or UNIQUE CONSTRAINT/INDEX on it. Then you would join fron that table to TableB.
Finally, what you might be after is an EXISTS, which would look like this:
SELECT B.trans_id, B.[name]
FROM dbo.TableB B
WHERE EXISTS(SELECT 1
FROM dbo.TableA A
WHERE A.ID_Trans = B.trans_id); --Odd that it's called ID_Trans in one table, and Trans_ID in another
As the comments mentioned your query does exactly what you asked it to do but I think you wanted something like:
select a.trans_id, a.name, b.name
from tableA a
inner join tableB b on a.trans_id = b.trans_id
group by a.trans_id, a.name, b.name
Since there are two rows in both table with same ID join will make them four. You can use distinct to remove duplicates:
select distinct a.trans_id, name
from tableA a
inner join tableB b
on a.id_trans = b.trans_id
But I would suggest to use exists:
select trans_id, name
from tableB b
exists (select 1 from tableA a where a.trans_id=b.trans_id)

Selecting Fields and Join Clause

I have two tables, TableA:
- Original_Location
- Units
and TableB:
- Original_Loc
- Adjacent_Loc
- Direction (up/down/left/right from original loc)
My goal is to return the original location, the adjacent location, the direction, and the number of units at the adjacent loc. So far, I've only been able to return the units from the original loc.
Here is what I've tried so far:
Select Original_Location,
Units,
TableB.Adjacent_Loc,
TableB.Direction
From TableA
Inner Join
Select *
From TableB
On TableA.Original_Location = TableB.Original_Loc
My thought is that I might need to change the fields I'm selecting before the inner join, or potentially join on Original_Location = Adjacent_Loc.
Your Join syntax is not right. First you don't need to "select" anything from Table B, your initial SELECT is getting data from the joined tables (A and B) as if they were 1 table. Secondly, you need to specify which fields to join the tables with.
Your join will be something like :-
From TableA Inner Join TableB
on TableA.Original_Loc = TableB.Original_Loc
Once you have got your joins right, you need to make another join to TableA to get the Units. This time you are joining the Adjacent_Loc in Table B to the Original_Location in Table A - which will have the Units value you need.
My example below uses aliases to identify each table (there are now 2 references to TableA so they need to be identified separately). So when you do the second join to TableA, this has the alias of c to differentiate it from the first TableA reference. You then need to select the Units from c.
Select a.Original_Location, c.Units, b.Adjacent_Loc, b.Direction
From TableA a Inner Join TableB b On a.Original_Location = b.Original_Loc
inner join TableA c on b.Adjacent_Loc = c.Original_Location

Update records only once with LEFT OUTER JOIN

I am trying to UPDATE Table A with records in Table B based on a LEFT OUTER JOIN based on two columns of data. So, for example, the JOIN from Table A might be USA-4 to match Table B's USA-4. Returning a result of XYZ to a different column. The problem I am having is the Table B contains multiple USA-4's and as a result Table A appears to be updating more than once. Is there a way to fix this? A different JOIN type?
UPDATE tablea a
SET USA-4 = (SELECT distinct USA-4 FROM tableb b WHERE a.id=b.id)

What means "table A left outer join table B ON TRUE"?

I know conditions are used in table joining. But I met a specific situation and the SQL codes writes like "Table A join table B ON TRUE"
What will happen based on the "ON TRUE" condition? Is that just a total cross join without any condition selection?
Actually, the original expression is like:
Table A LEFT outer join table B on TRUE
Let's say A has m rows and B has n rows. Is there any conflict between "left outer join" and "on true"? Because it seems "on true" results a cross join.
From what I guess, the result will be m*n rows. So, it has no need to write "left outer join", just a "join" will give the same output, right?
Yes. That's the same thing as a CROSS JOIN.
In MySQL, we can omit the [optional] CROSS keyword. We can also omit the ON clause.
The condition in the ON clause is evaluated as a boolean, so we could also jave written something like ON 1=1.
UPDATE:
(The question was edited, to add another question about a LEFT [OUTER] JOIN b which is different than the original construct: a JOIN b)
The "LEFT [OUTER] JOIN" is slightly different, in that rows from the table on the left side will be returned even when there are no matching rows found in the table on the right side.
As noted, a CROSS JOIN between tables a (containing m rows) and table b containing n rows, absent any other predicates, will produce a resultset of m x n rows.
The LEFT [OUTER] JOIN will produce a different resultset in the special case where table b contains 0 rows.
CREATE TABLE a (i INT);
CREATE TABLE b (i INT);
INSERT INTO a VALUES (1),(2),(3);
SELECT a.i, b.i FROM a LEFT JOIN b ON TRUE ;
Note that the LEFT JOIN will returns rows from table a (a total of m rows) even when table b contains 0 rows.
A cross join produces a cartesian product between the two tables, returning all possible combinations of all rows. It has no on clause because you're just joining everything to everything.
Cross join does not combine the rows, if you have 100 rows in each table with 1 to 1 match, you get 10.000 results, Innerjoin will only return 100 rows in the same situation.
These 2 examples will return the same result:
Cross join
select * from table1 cross join table2 where table1.id = table2.fk_id
Inner join
select * from table1 join table2 on table1.id = table2.fk_id
Use the last method
The join syntax's general form:
SELECT *
FROM table_a
JOIN table_b ON condition
The condition is used to tell the database how to match rows from table_a to table_b, and would usually look like table_a.some_id = table_b.some_id.
If you just specify true, you will match every row from table_a with every row of table_b, so if table_a contains n rows and table_b contains m rows the result would have m*n rows.
Most(?) modern databases have a cleaner syntax for this, though:
SELECT *
FROM table_a
CROSS JOIN table_b
The difference between the pure cross join and left join (where the condition is forced to be always true, as when using ON TRUE) is that the result set for the left join will also have rows where the left table's rows appear next to a bunch of NULLs where the right table's columns would have been.

Two tables connected by foreign key

I need to connect two tables in SQL Server: Table A has a primary key called IDTableA (integer field) and Table B has a primary key IDTableB (integer field as well).
Table A contains a foreign key IDTableB whereby I want to connect both tables, this field is of type integer and its value is 0.
My problem is that since there is no record in Table B whose ID is 0, do not show me those records from table A with a 0 stored in the foreign key.
The relationship between both tables is: a record in Table A may belong to one or no record in the table B. Therefore, the default value of the foreign key in table A is 0.
I tried connecting the tables with INNER JOIN and LEFT OUTER JOIN but it does not work and left no records show. What I can do?.
Thanks.
My SQL statement:
Select TableA.*
From TableA
inner join TableB on TableA.IdTableB = TableB.IdTableB
The Solution:
Select TableA.*
From TableA
LEFT JOIN TableB on TableA.IdTableB = TableB.IdTableB
More Info:
LEFT JOIN vs. LEFT OUTER JOIN in SQL Server
Try to use left join only
Something like this
Select *
from table_1 tbl1
left join table_2 tbl2 on tbl2.id = tbl1.id
An inner join is the most common join operation used in applications and can be regarded as the default join-type. Inner join creates a new result table by combining column values of two tables (A and B) based upon the join-predicate. The query compares each row of A with each row of B to find all pairs of rows which satisfy the join-predicate. When the join-predicate is satisfied, column values for each matched pair of rows of A and B are combined into a result row.
FROM Table A <renametablehere>
Inner Join Table B <renametablehere>
On <renamedtablename for A>.ID = <renamed table name for b>B.ID