Join same table with different column - sql

Hi This may be a stupid question but I have a scenario where my columns tl1,tl2 and tl3 refers to column id table structure is below,
id | name | email | tl1 | tl1 | tl3 |
1 | xyz |x#g.com| null| 1 | 2 |
======================================
2 | abc |z#g.com| null| 1 | 3 |
======================================
3 | def |d#g.com| 1 | 2 | 4 |
SO need to write a query to get the name of tl1,tl2 and tl3,
like below
id | name | email | tl1 | tl1 | tl3 |
1 | xyz |x#g.com| null| xyz | abc |
======================================
2 | abc |z#g.com| null| xyz | def|
======================================
3 | def |d#g.com| xyz | abc | ghi |
I am not able to create query for this scenario, I actually created one but not getting unique records
This is the query which I tried
select distinct a.branch_code,a.email,a.partner_name,a.role_assigned,a.category,b.partner_name as tl1,
c.partner_name as tl2,d.partner_name as tl3
from branch_master as a
left join branch_master as b on b.tl1 = a.branch_code
left join branch_master as c on c.tl2 = a.branch_code
left join branch_master as d on d.tl3 = a.branch_code
Any help would be appreciated.

You need to left join the table 3 times with itself:
select
t.id, t.name, t.email,
t1.name name1, t2.name name2, t3.name name3
from tablename t
left join tablename t1 on t1.id = t.tl1
left join tablename t2 on t2.id = t.tl2
left join tablename t2 on t3.id = t.tl3

First, this is generally a bad data format -- typically, you want the values in different tables. There are some cases where it might make sense to have the data across columns -- for instance, if role are different: submitted_by, processed_by, approved_by. But generally, you want a junction/association table.
The solution to your problem, though, is multiple left joins:
select t.*, t1.email as email1, t2.email as email2, t2.email as email3
from t left join
t t1
on t1.tl1 = t.id left join
t t2
on t2.tl2 = t.id left join
t t3
on t3.tl3 = t.id;

Related

Joining Two Tables, Same ID - Return both IDs even if Null

I have two tables
+-----+----------+
| SKU | Quantity |
+-----+----------+
| ABC | 30 |
| DEF | 40 |
+-----+----------+
+-----+----------+
| SKU | OnOrder |
+-----+----------+
| ABC | 90 |
| XYZ | 80 |
+-----+----------+
I want to join both tables on SKU when there is a match, but also return SKU from both tables when there isn't a match. So the results would be:
+-----+---------+---------+
| SKU | OnOrder | OnOrder |
+-----+---------+---------+
| ABC | 90 | 30 |
| DEF | 40 | |
| XYZ | | 80 |
+-----+---------+---------+
I'm thinking this would be accomplished by using a left join and a right join and by doing a union but I can't seem to get the code right.
Your help is much appreciated!
You can use a full join:
select coalesce(t1.sku, t2.sku), t1.quantity, t2.onorder
from table1 t1 full join
table2 t2
on t1.sku = t2.sku;
If your database doesn't support full join, the best workaround is probably:
select t1.sku, t1.quantity, t2.onorder
from table1 t1 left join
table2 t2
on t1.sku = t2.sku
union all
select t2.sku, null, t2.onorder
from table2
where not exists (select 1 from table1 t1 where t1.sku = t2.sku);
You can first select all the SKU values and then join that to both tables:
with skus(sku) as (
select sku from table1
union
select sku from table2
)
select a.sku, b.quantity, c.onorder
from skus a
left join table1 b on a.sku = b.sku
left join table2 c on a.sku = c.sku;

Why isn't Teradata EXCEPT returning expected results?

Why isn't EXCEPT returning expected results? I feel like this should work, but it returns zero rows. However, if I do a count of order-buid-tie rows in T3 that aren't in t2, I get thousands of results and vice versa.
Manual review
--first table (T3) without T2 match --178k
select count(*) --178K
from LAB3.Report_stg st3
left join LAB2.Report_stg st2
on st3.order_num = st2.order_num and st3.buid= st2.buid and st3.tie_nbr = st2.tie_num
where st2.tie_num is null
--second table (t2) without match in first (T3)
select count(*) --12.5M
from LAB2.Report_stg st2
left join LAB3.Report_stg st3
on st3.order_num = st2.order_num and st3.buid = st2.buid and st3.tie_num = st2.tie_num
where st3.tie_num is null
Let's try EXCEPT. I expect 178k rows here and get zero
--to avoid cartesian join
--select all mismatched tie_nums
--unless (EXCEPT if) that tie_num exists as a matched set between the two tables
select t3.order_num, t3.buid, t3.tie_num as t3_tie
from LAB3.Report_stg t3
left join LAB2.Report_stg t2
on t3.order_num = t2.order_num and t3.buid = t2.buid and t3.tie_num <> t2.tie_num
except
(select st3.order_num, st3.buid, st3.tie_num
from LAB3.Report_stg st3
left join LAB2.Report_stg st2
on st3.order_num = st2.order_num and st3.buid = st2.buid and st3.tie_num = st2.tie_num
)
Argh, I figured it out! So, the second part of the clause (inside the EXCEPT SELECT) needs to be an INNER JOIN to achieve the desired effect. Again, what I was trying to pull was all the Ties in T3 on the same T2 Orders that don't have a match between the tables.
--to avoid cartesian join
--select all mismatched tie_nums
--unless (EXCEPT if) that tie_num exists as a matched set between the two tables
select t3.order_num, t3.buid, t3.tie_num as t3_tie
from LAB3.Report_stg t3
left join LAB2.Report_stg t2
on t3.order_num = t2.order_num and t3.buid = t2.buid and t3.tie_num <> t2.tie_num
except
(select st3.order_num, st3.buid, st3.tie_num
from LAB3.Report_stg st3
INNER join LAB2.Report_stg st2
on st3.order_num = st2.order_num and st3.buid = st2.buid and st3.tie_num = st2.tie_num
)
Example:
T3
| Order_Num | Tie_Num |
| -------- | -------------- |
| 123 | 1 |
| 123 | 2 |
| 123 | 3 |
| 456 | 1|
| 456 | 4|
T2
| Order_Num | Tie_Num |
| -------- | -------------- |
| 123 | 2 |
| 123 | 4 |
| 123 | 5 |
| 456 | 1|
| 456 | 3|
Results using query above
T3
| Order_Num | Tie_Num |
| -------- | -------------- |
| 123 | 1 |
| 123 | 3 |
| 456 | 4|
So, ideally, I'd union this with an inverse to get the order-ties in T2 that aren't in t3 into the same result set. But then that means I've just written a manual FULL OUTER JOIN
SMH

Joining tables in Postgres

I have a table...
col1 | id | col3|
---------------------
1 |123 | |
2 |456 | |
3 |789 | |
And I have another table...
id | name |
------------
123 | Tom |
456 | Kate |
789 | Pork |
101 |Winter|
102 |Roll |
I want to join the tables together to get a result that looks like this...
col1 | id | col3| name
----------------------------
1 |123 | | Tom
2 |456 | | Kate
3 |789 | | Pork
Can someone help me please?
Thanks in advance
If you only want the data where id from one table matches to id at another table then you can do an inner join like this:
SELECT *
FROM table1
INNER JOIN table2 ON table2.id = table1.id
If you want all the data from the first table but only matched id data from the second table then you can do this:
SELECT *
FROM table1
LEFT JOIN JOIN table2 ON table2.id = table1.id
For more information about Joins you an refer to this link - SQL joins
use inner join between two tables
select col1,table1.id,col3,name from table1
inner join table2 on table1.id =table2.id
Do the JOIN :
SELECT t1.*, t2.name
FROM table1 t1 INNER JOIN
table2 t2
ON t1.id = t2.id;

Join three tables with counts

I have these three tables (Soknad, Prognose and Did) in the SQL Server database:
Table Soknad has columns: S_ID (key), S_REFNR
Table Prognose has columns: P_ID (key), P_S_ID
Table Did has columns: D_ID (key), D_S_ID, Did_Something
Prognose.P_S_ID is foreign key to Soknad.S_ID.
Did.D_S_ID is foreign key to Soknad.S_ID.
The tables are like this:
SOKNAD
S_ID | S_REFNR |
1 | abc |
2 | cbc |
3 | sdf |
PROGNOSE
P_ID | P_S_ID |
10 | 1 |
11 | 2 |
DID
D_ID | D_S_ID | D_Did_Something |
100 | 1 | 1 |
101 | 1 | 1 |
102 | 1 | 0 |
103 | 2 | 1 |
104 | 2 | 1 |
I want to join these tables (like a view or select statement). From the Did table a count of column Did_Something should be returned, as well as a count of the same column where the value is 1 (one).
The result should be:
S_ID | S_REFNR | P_ID | Count_D_Did_Something | Count_D_Did_Something_Is_One |
1 | abc | 10 | 3 | 2 |
2 | cbc | 11 | 2 | 2 |
3 | sdf | | | |
Any help would be appreciated!
I believe what you want to do is join two tables and put the counts where the rows match the left table in separate columns for each table.
This would accomplish that.
select t1.id, count(t2.id) t2_count , count(t3.id) t3_count
from table1 as t1
left outer join table2 as t2 on t2.table1_id = t1.id
left outer join table3 as t3 on t3.table1_id = t1.id
group by t1.id;
To accomplish the counts you want based on criteria from one of the outer joined tables, you can do that this way, using a derived table...
select t1.id, count(t2.id) t2_count, count(tt2.mCount) Did_SomethingCount, count(t3.id) t3_count
from table1 as t1
left outer join table2 as t2 on t2.table1_id = t1.id
left outer join (select count(*), table1_id mCount from table2 where Did_Something = 1 group by table1_id) as tt2 on tt2.table1_id = t1.id
left outer join table3 as t3 on t3.table1_id = t1.id
group by t1.id;
Here you go:
select s.s_id,
p.p_id,
count(d.Did_Something) as Count_D_Did_Something, -- nulls won't be counted
sum(CASE WHEN d.Did_Something = 1 THEN 1 ELSE 0 END) as Count_D_Did_Something_is_one
from Soknad as s
left join Prognose as p on p.P_S_ID = s.s_id
left join Did as d on d.D_S_ID = s.s_id
This should be simply give the results you need. Note, I simply summed up when you want count to be for values having one,
SELECT S.S_ID, S.REFNR, P.P_ID, COUNT(D.D_DID_SOMETHING) AS COUNT_D_DID_SOMETHING,
SUM(D_DID_SOMETHING) AS COUNT_D_DID_SOMETHING_IS_ONE
FROM SOKNAD AS S
INNER JOIN PROGNOSE AS P
ON P.P_S_ID = S.S_ID
INNER JOIN DID AS D
ON D.D_S_ID = S.S_ID
GROUP BY S.S_ID, S.REFNR, P.P_ID

Left Join to select all record from table1 and single (optional) record of table2

In my database i have to table with one to many(optional) relationship 1....0,*
Table1:
+--+---------+
|id| name |
+--+---------+
| 1| user1 |
| 2| user2 |
| 3| user3 |
+--+---------+
Table2
+--+------+-------+
|id|tb1_ID|city |
+--+------+-------+
| 1| 1 | a |
| 2| 1 | b |
| 3| 2 | c |
+--+------+-------+
Now here i want all present records from table 1 and Top 1 element of table2(for each table 1 row)
Like
+----+------+----+--------+---------+
|p.id|p.name|c.id|c.tb1_ID|c.city |
+----+------+----+--------+---------+
| 1 | user1| 1 | 1 | a |
| 2 | user2| 3 | 2 | c |
| 3 | user3|null| null | null |
+----+------+----+--------+---------+
HOw???
For example with this WITH common_table_expression and ROW_NUMBER function:
WITH cte AS(
SELECT t1.id AS t1ID
, t1.name
, t2.id AS t2ID
, t2.tb1_ID
, t2.city
, ROW_NUMBER()OVER(Partition By t1.id Order By t2.id)AS t1RowNum
FROM Table1 t1 LEFT OUTER JOIN Table2 t2 ON t1.id=t2.tb1_ID
)
SELECT cte.*
FROM cte
WHERE t1RowNum = 1
You'll have to use a subquery with OUTER APPLY to isolate the single row in the right table.
select t1.*, t2.*
from table1 t1
outer apply
(
select top 1 *
from table2
where tb1_id = t1.id
order by id
) as t2
Assuming you have a 1 to many relationship you want to use a LEFT OUTER JOIN:
SELECT p.id, p.name, c.id, c.tb1_ID, c.city
FROM Table1 p
LEFT OUTER JOIN Table2 c
ON p.id = c.tb1_ID
If you have a many to many you'll need to decide how you're limiting table 2.