Joining multiple tables into one under one Id - sql

I have dozen of tables with following format:
Table 1
[idA] [numA]
NULL 8
1 10
2 15
3 16
Table 2
[idB] [numB]
2 14
3 30
4 32
Table 3
[idC] [numC]
NULL 56
1 24
4 37
5 36
...
Now, I'm not sure how to formulate T-Sql query in order to produce following result:
[id] [numA] [numB] [numC] ...
NULL 8 0 56
1 10 0 24
2 15 14 0
3 16 30 0
4 0 32 37
5 0 0 36
Are there any suggestions on how to solve this?

I offer a solution with the full outer join, because that seems like the natural approach:
SELECT coalesce(a.id, b.id, c.id, . . .) as id,
a.NumA, b.NumB, c.NumC, . . .
FROM TableA a full outer join
TableB b
on a.id = b.id full outer join
TableC c
on coalesce(a.id, b.id) = c.id
However, the query needs to be written carefully, to keep the coalesces in line. The one advantage of this approach is that it should use indexes on the id columns for the query.

please try this
select id, max(numa),max(numb),max(numc) from
(
select id,numa,0 as numb,0 as numc from tb1
union all
select id,0 as numa,numb as numb,0 as numc from tb2
union all
select id,0 as numa,0 as numb,numc as numc from tb3
)X
group by id
order by id
Thanks
Rajath

SELECT Maintable.id,
Table1.numA,
Table2.numB,
Table3.numC
FROM (SELECT ida AS id
FROM Table1
UNION
SELECT idb AS id
FROM Table2
UNION
SELECT idc AS id
FROM Table3) MainTable
LEFT JOIN Table1
ON Maintable.id = Table1.Ida
LEFT JOIN Table2
ON Maintable.id = Table2.idB
LEFT JOIN Table3
ON Maintable.id = Table3.idC

Related

how to join with complecated condition in redshift

I have following table1
id name
1 A
3 B
and table2
id label value
1 a 10
1 b 11
1 c 12
2 a 13
2 b 14
2 c 15
3 a 16
3 b 17
3 c 18
My desired result is following.I'd like to join table1 and table2 in label=a and b
I guess I must join twice in each condition..
id name a b
1 A 10 11
3 B 16 17
I tried following one, but I get only result in label = a
select *
from table1
left join table2 using(id)
where label in ('a')
Are there any good way to achieve this?
I guess we need transpose
Thanks
Redshift doesn't have a native pivot function so you need to do it using a case statement:
SELECT
table1.id,
table1.name,
SUM(CASE WHEN table2.label = 'a' THEN table2.value END) AS a,
SUM(CASE WHEN table2.label = 'b' THEN table2.value END) AS b
FROM table1
LEFT JOIN table2
ON table1.id = table2.id
GROUP BY table1.id, table1.name
See this link also:
Pivot for redshift database

How to generate loop kind of behaviour in SQL query to fetch multiple queries & compare results?

I am unable to generate a looping kind of behaviour in a SQL query.
I am having two tables:
Table A
Id Brand Prod_Id Alt_Prod_Id
1 A 2 5
2 B 3 9
3 C 5 9
Table B
Id Prod_Id Rate
1 2 5
2 3 9
2 5 7
2 9 9
Rate in Table B needs to be looked up for each brands Prod_ID & Alt_Prod_Id & select the least value between 2 found value
The expected result / output is:
Brand Min_Prod_Val
A 5
B 9
C 7
Can this be done in a query?
Thanks!
You could join tableb twice (once for prod_id, another for alt_prod_id), and then select the smallest rate:
select
a.brand,
least(b1.rate, b2.rate) min_prod_val
from tablea a
inner join tableb b1 on b1.prod_id = a.prod_id
inner join tableb b2 on b2.prod_id = a.alt_prod_id
It is unclear which database you are using. If that's SQL Server: it does not support least(), so you need a case expression:
case when b1.rate < b2.rate then b1.rate else b2.rate end min_prod_val
You can use a single join and GROUP BY the brand:
SELECT a.Brand,
MIN( b.rate ) AS min_prod_val
FROM TableA A
INNER JOIN TableB b
ON ( b.prod_id IN ( a.prod_id, a.alt_prod_id ) )
GROUP BY a.Brand
Or you can use a correlated sub-query:
SELECT a.Brand,
(
SELECT MIN( rate )
FROM TableB b
WHERE b.prod_id IN ( a.prod_id, a.alt_prod_id )
) AS min_prod_val
FROM TableA A
db<>fiddle

Join tables with different data in rows

I have two tables like this
t1
id value1
BMC 16
EC 22
LLU 60
MC 274
UHC 54
UHS 28
t2
id value2
BMC 5
e900 4
EC 7
LLU 2
MC 1
How could I get this out put using sql server? I have used full outer join also. But its not gives me correct results
BMC 16 5
EC 22 7
LLU 60 2
MC 274 1
UHC 54
UHS 28
e900 4
Here is my outer join, Its for two select statements. Not for tables. But those select statements gives above results (t1, t2)
SELECT * FROM
(
SELECT b.EntityCode, COUNT('a') AS GroupCountUser1 FROM #TempUser a INNER JOIN OP_TB_TRN_Entity b
ON a.Entity=b.EntityID
GROUP BY b.EntityCode
) t1
FULL OUTER JOIN
(SELECT b.EntityCode, COUNT('a') AS GroupCountUser2 FROM #TempUser1 a INNER JOIN OP_TB_TRN_Entity b
ON a.Entity=b.EntityID
GROUP BY b.EntityCode) t2
ON t1.EntityCode = t2.EntityCode
Guessing you are forgetting to coalesce the IDs, try
Select coalesce( A.Id, B.Id) id,
A.Value1, B.Value2
From A Full Join B On A.Id = B.Id
Select concat( t1.value1, t2.value2) as totalvalue
From t1 join t2 where t1.Id = t2.Id
If i understand what you're asking, this should help.

SQL: Outputting Multiple Rows When Joining From Same Table

My question is this: Is it possible to output multiple rows when joining from the same table?
With this code for example, I would like it to output 2 rows, one for each table. Instead, what it does is gives me 1 row with all of the data.
SELECT t1.*, t2.*
FROM table t1
JOIN table t2
ON t2.id = t1.oldId
WHERE t1.id = '1'
UPDATE
Well the problem that I have with the UNION/UNION ALL is this: I don't know what the t1.oldId value is equal to. All I know is the id for t1. I am trying to avoid using 2 queries so is there a way I could do something like this:
SELECT t1.*
FROM table t1
WHERE t1.id = '1'
UNION
SELECT t2.*
FROM table t2
WHERE t2.id = t1.oldId
SAMPLE DATA
messages_users
id message_id user_id box thread_id latest_id
--------------------------------------------------------
8 1 1 1 NULL NULL
9 2 1 2 NULL 16
10 2 65 1 NULL 15
11 3 65 2 2 NULL
12 3 1 1 2 NULL
13 4 1 2 2 NULL
14 4 65 1 2 NULL
15 5 65 2 2 NULL
16 6 1 1 2 NULL
Query:
SELECT mu.id FROM messages_users mu
JOIN messages_users mu2 ON mu2.latest_id IS NOT NULL
WHERE mu.user_id = '1' AND mu2.user_id = '1' AND ((mu.box = '1'
AND mu.thread_id IS NULL AND mu.latest_id IS NULL) OR mu.id = mu2.latest_id)
This query fixes my problem. But it seems the answer to my question is to not use a JOIN but a UNION.
You mean one row for t1 and one row from t2?
You're looking for UNION, not JOIN.
select * from table where id = 1
union
select * from table where oldid = 1
If you are trying to multiply rows in a table, you need UNION ALL (not UNION):
select *
from ((select * from t) union all
(select * from t)
) t
I also sometimes use a cross join to do this:
select *
from t cross join
(select 1 as seqnum union all select 2) vals
The cross join is explicitly multiplying the number of rows, in this case, with a sequencenumber attached.
Well, since it's the same table, you could do:
SELECT t2.*
FROM table t1
JOIN table t2
ON t2.id = t1.oldId
OR t2.id = t1.id
WHERE t1.id = '1'

SQL Query to sum fields from different tables

I'm a humble programmer that hates SQL ... :) Please help me with this query.
I have 4 tables, for example:
Table A:
Id Total
1 100
2 200
3 500
Table B
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table C
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table D
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
I need to make a SELECT that shows the Id, the Total and the SUM of the Amount fields of tables B, C and D like this
Id Total AmountB AmountC AmountD
1 100 43 43 43
2 200 55 55 55
3 500 65 65 65
I've tried with a inner join of the three tables by the Id and doing a sum of the amount fields but results are not rigth. Here is the wrong query:
SELECT dbo.A.Id, dbo.A.Total, SUM(dbo.B.Amount) AS Expr1, SUM(dbo.C.Amount) AS Expr2, SUM(dbo.D.Amount) AS Expr3
FROM dbo.A INNER JOIN
dbo.B ON dbo.A.Id = dbo.B.ExtId INNER JOIN
dbo.C ON dbo.A.Id = dbo.C.ExtId INNER JOIN
dbo.D ON dbo.A.Id = dbo.D.ExtId
GROUP BY dbo.A.Id, dbo.A.Total
Thanks in advance, its just that I hate SQL (or that SQL hates me).
EDIT: I had a typo. This query is not giving the right results. Extended the example.
Or you can take advantage of using SubQueries:
select A.ID, A.Total, b.SB as AmountB, c.SC as AmountC, d.SD as AmountD
from A
inner join (select ExtID, sum(Amount) as SB from B group by ExtID) b on A.ID = b.ExtID
inner join (select ExtID, sum(Amount) as SC from C group by ExtID) c on c.ExtID = A.ID
inner join (select ExtID, sum(Amount) as SD from D group by ExtID) d on d.ExtID = A.ID
From your description, this query should give you an error as you are using the non-existent column dbo.A.Amount in your group by. Changing this to dbo.A.Total might be what you need.
If you need all the amounts together, then try this query:
select A.Id, A.Total, sum(B.Amount + C.Amount + D.Amount) AS Total_Amount
from A
inner join B on A.Id = B.ExtId
inner join C on A.Id = C.ExtId
inner join D on A.Id = D.ExtId
group by A.Id, A.Total;
This one also works well
SELECT (SELECT SUM(Amount) FROM TableA) AS AmountA,
(SELECT SUM(Amount) FROM TableB) AS AmountB,
(SELECT SUM(Amount) FROM TableC) AS AmountC,
(SELECT SUM(Amount) FROM TableD) AS AmountD
This might help other users.
SELECT Total=(Select Sum(Amount) from table a)+(Select Sum(Amount) from table b)+(Select Sum(Amount) from table c)
Try this code
SELECT Total=isnull((Select Sum(Isnull(Amount,0)) from table a),0)+isnull((Select Sum(isnull(Amount,0)) from table b),0)+isnull((Select Sum(isnull(Amount,0)) from table c),0)