Get records using left outer join - sql

I have two tables as given below
Table A Table B Table C
============= ============== =========
Id Name Id AId CId Id Name
1 A 1 1 1 1 x
2 B 2 1 1 2 y
3 C 3 2 1 3 z
4 D 4 2 3 4 w
5 E 5 3 2 5 v
Now I want all the records of Table A with matching Id column CId from Table B where CId = 1.
So the output should be like below :
Id Name CId
1 A 1
2 B 1
3 C 1
4 D Null
5 E Null
Can anyone help me please?

This does what you want:
SELECT
A.Id,
A.Name,
CASE B.CId WHEN 1 THEN 1 ELSE NULL END AS CId
FROM
A LEFT JOIN B ON A.Id = B.Id
This is not about LEFT JOINing. You could as well do it with an INNER JOIN. When you don't want the 3 and 2 of column CId to appear you would still have to filter with WHERE and therefore the rows with Id 4 and 5 would not appear, which is not what you want.
EDIT:
Given this test data:
create table A (Id int, Name varchar(5));
insert into A values
(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D'),
(5, 'E');
create table B (Id int, AId int, CId int);
insert into B values
(1,1,1),
(2,1,1),
(3,2,1),
(4,2,3),
(5,3,2);
my query does not give a cartesian product. Read and try before downvoting. Anyway, it was not clear to me what you want to achieve, now I've joined on AId column and with this query:
SELECT DISTINCT
A.Id,
A.Name
, CASE
WHEN B.CId > 1 THEN 1
WHEN B.CId = 1 THEN 1
ELSE NULL END AS CId
FROM
A LEFT JOIN B ON A.Id = B.AId
and it also gives the right output, like the first before. If this is still not what you want, your test data is wrong or I absolutely don't get it.

Try something like this:
SELECT TableA.Id, TableA.Name, TableB.CId
FROM TableA
LEFT OUTER JOIN TableB ON TableA.Id = TableB.CId
WHERE TableB.CId = 1
Hope this helps.
Edit:
The output you desired, can be achieved if you match TableA's ID column with TableB's ID column, NOT TableB's CId column. Try below which I tested in my pc and gives thee similar output you needed.
select TableA.Id, TableA.Name, TableB.CId
from TableA
left outer join TableB on TableA.Id = TableB.Id
and TableB.CId in
(
select TableB.CId
from TableB
left outer join TableC on TableB.CId = TableC.Id
WHERE TableB.CId = 1
)
group by TableA.Id, TableA.Name, TableB.CId
Please inform if I guess it right. Check the column names.

Related

Full outer join like functionality but merging columns

TableA
id | symbolA
1 m
2 n
4 o
TableB
id | symbolB
2 p
3 q
5 r
I'd like the following result:
id | symbolA | symbolB
2 n p
1 m NULL
4 o NULL
3 NULL q
5 NULL r
This is what I've already tried:
SELECT
TableA.id,
TableB.id,
TableA.symbolA,
TableB.symbolB
FROM
TableA
FULL OUTER JOIN
TableB
ON
TableA.id = TableB.id
NewTable
TableA.id | TableA.symbolA | TableB.id | TableA.symbolB
2 n 2 p
1 m NULL NULL
4 o NULL NULL
NULL NULL 3 q
NULL NULL 5 r
I've already tried a full outer join in combination with a coalesce but it doesn't exactly give me the the above desired output. The language is BigQuery, though I'm hoping there's nothing idiosyncratic about my request that wouldn't make it SQL language agnostic. Thanks.
You are almost there. You just need to merge the two id columns.
For this, you can use coalesce():
select
coalesce(a.id, b.id) id,
a.symbola,
b.symbolb
from tablea a
full outer join tableb b on a.id = b.id
The following syntax that joins with using should also work (most databases that support full join allow this):
select
id,
a.symbola,
b.symbolb
from tablea a
full outer join tableb b using(id)

Update a table with data from another not related table

I have three tables A,B and C.
A and B are connected a foreign key A.category_id=B.id ,
A and C have the same number of rows.
A
id category_id value1 value2
1 null 'A' null
2 null 'B' null
3 null 'C' null
4 null 'D' null
B
id category
1 0
2 1
C
id category
1 0
2 1
3 1
4 0
Expected result:
A
id value
1 1
2 2
3 2
4 1
I would like to receive updated A table where category_id will be id from table B based on table C category.
I have tried
UPDATE A SET
A.category_id = (
select B.id from A
left JOIN C
ON A.id = C.id
left join B on B.category=C.category
)
WHERE A.id IN (SELECT C FROM C WHERE A.id = C.id);
but then I received ORA-01427 single-row subquery returns more than one row tips
You are missing a correlation clause in the subquery:
update A
set category_id = (select B.id
from C join
B
on B.category = C.category
where A.id = C.id
)
where exists (select 1 from C where A.id = C.id);
To correlated a query, you refer to the outer reference typically in a where condition. You don't repeat the table reference in the from clause.
Note that an outer join is unnecessary. If there is no match, the value will be NULL.

How does this SQL Left join on itself work?

CREATE TABLE dbo.Temp_Test
(Main_id int,
Unique_id char(1) )
insert into Temp_Test(Main_id,Unique_id)
values (1, 'a'),
(2, 'b'),
(3, 'c'),
(4, 'c')
SELECT r.Main_Id, r.Unique_ID, x.Main_Id, x.Unique_id
FROM dbo.Temp_Test r
LEFT JOIN dbo.Temp_Test x
ON r.Unique_ID = x.Unique_ID
AND x.Main_Id < r.Main_Id
WHERE x.Main_Id IS NULL
I'm trying to understand how this query works. When running it in steps, it just made me more confused. When it's ran just as
SELECT r.Main_Id, r.Unique_ID, x.Main_Id, x.Unique_id
FROM dbo.Temp_Test r
LEFT JOIN dbo.Temp_Test x
ON r.Unique_ID = x.Unique_ID
the results turn into
Main_ID Unique_ID Main_id Unique_id
1 a 1 a
2 b 2 b
3 c 3 c
3 c 4 c
4 c 3 c
4 c 4 c
But when ran with the x.main_id < r.main_id filter, we get
Main_ID Unique_ID Main_id Unique_id
1 a NULL NULL
2 b NULL NULL
3 c NULL NULL
4 c 3 c
What happened to the 4 C 4 C row?
When you do left join, all the records from the left table will be part of the result. If query finds match from second table, it will show them in result or else will simply print NULL.
In first query, it did find an match with Unique_id's so it gave you results with all possible pairs.
In second query, since there were no records where Main_id was greater in first table (for 1,2,3) it returned NULL for second table.
Whereas, it found Main Id 4 from table at the left to be greater than 3 from table at the right so it displayed the result.
Since Main_id 4 from left table is not greater than the Main_id 4 from the right table, that is not a part of the result.

SQL joining 2 tables without repeating values

I have 2 tables with a 1:n relationship.
I want to join them without repeating (duplicating) the values from the one table.
First, I have a table with budgets:
id name budget
1 John 1000
2 Kim 3000
And second I have a table of spendings:
id amount
1 112
1 145
1 211
The result should look like this:
id name budget amount
1 John 1000 112
1 null null 145
1 null null 211
2 Kim 3000 null
Output could also be: (this is not important)
id name budget amount
1 null null 112
1 John 1000 145
1 null null 211
2 Kim 3000 null
Is this possible with SQL?
Here a join that repeats the values:
create temporary table a (id1 int,name varchar(10),budget int);
insert into a (id1,name,budget) values(1,'Maier',1000),(2,'Mueller',2000);
create temporary table if not exists b (id2 int,betrag int);
insert into b (id2,betrag) values(1,100),(1,133),(1,234);
select * from a left join b
on a.id1=b.id2
;
The keyword DISTINCT is used to eliminate duplicate rows from a query result:
select distinct b.id, b.name, b.budget, s.amount
from budgets b left join spendings s
on b.id = s.id;
You can also use Group By clause which works similarly like Distinct.In that case,
select b.id, b.name, b.budget, s.amount
from budgets b left join spendings s
on b.id = s.id
group by b.id, b.name, b.budget, s.amount;
create table a (id1 int,name varchar(10),budget int)
insert into a (id1,name,budget) values(1,'Maier',1000)
insert into a (id1,name,budget) values(2,'Mueller',2000)
create table b (id2 int,betrag int)
insert into b (id2,betrag) values(1,100)
insert into b (id2,betrag) values(1,133)
insert into b (id2,betrag) values(1,234)
insert into b (id2,betrag) values(2,300)
insert into b (id2,betrag) values(2,400)
select a.id1, CASE WHEN c.themin IS NOT NULL THEN a.name ELSE NULL END AS [name],
CASE WHEN c.themin IS NOT NULL THEN a.budget ELSE NULL END AS [budget],
b.*
from a
LEFT join b on a.id1=b.id2
LEFT OUTER JOIN (SELECT MIN(betrag) AS [themin], id2 FROM b GROUP BY id2) c ON a.id1 = c.id2 AND b.betrag = c.themin

SQL Select Statement issue - returning rows conditionally on a 2nd table

I could really use some help with the following SQL Select statement scenario:
I need to select all rows from a table conditionally depending on whether a userID has already entered data into a second table with the same ID.
Example:
Select all rows from TABLE A for idNumber where idNumber not in
TABLE B
but for each idNumber that IS in TABLE B, still return row unless a
specific userID is in that row in TABLE B.
TABLE A
========
idNumber|type|Date
1 A 01/01/01
2 A 01/01/01
3 B 01/01/01
4 B 01/01/01
5 B 01/01/01
TABLE B
========
idNumber|type|userID
1 A 0000
3 B 0000
4 B 1111
userID to exclude records for = 1111
SQL Query should return:
idNumber|type|Date
1 A 01/01/01
2 A 01/01/01
3 B 01/01/01
5 B 01/01/01
Apologies for the long winded post but i hope it makes sense.
Many thanks in advance,
ukjezza.!!
Select idNumber, type, Date
From TableA
Where Not Exists (
Select 1
From TableB
Where TableB.idNumber = TableA.idNumber
And TableB.userID = 1111
)
Another choice:
Select TableA.idNumber, TableA.type, TableA.Date
From TableA
Left Join TableB
On TableB.idNumber = TableA.idNumber
And TableB.userId = 1111
Where TableB.idNumber Is Null
Looks like a LEFT JOIN and COALESCE could take care of it:
SELECT a.*
FROM TableA as a
LEFT JOIN TableB as b
ON a.idNumber = b.idNumber
WHERE COALESCE(b.userID, -1) != 1111
select A.*
from TableA as A
left outer join TableB as B
on A.idNumber = B.idNumber
where B.idNumber is null or
B.userID <> '1111'