how to join with complecated condition in redshift - sql

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

Related

How to select rows by max value from another column in Oracle

I have two datasets in Oracle Table1 and Table2.
When I run this:
SELECT A.ID, B.NUM_X
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.ID=B.ID
WHERE B.BOOK = 1
It returns this.
ID NUM_X
1 10
1 5
1 9
2 2
2 1
3 20
3 11
What I want are the DISTINCT ID where NUM_X is the MAX value, something like this:
ID NUM_x
1 10
2 2
3 20
You can use aggregation:
SELECT A.ID, MAX(B.NUM_X)
FROM TABLE1 A LEFT JOIN
TABLE2 B
ON A.ID = B.ID
WHERE B.BOOK = 1
GROUP BY A.ID;
If you wanted additional columns, I would recommend window functions:
SELECT A.ID, MAX(B.NUM_X)
FROM TABLE1 A LEFT JOIN
(SELECT B.*,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY NUM_X DESC) as seqnum
FROM TABLE2 B
) B
ON A.ID = B.ID AND B.seqnum = 1
WHERE B.BOOK = 1
GROUP BY A.ID;

Conditional sum in SQL (SAS) (SUMIFS equivalent)

Let say I am working under SAS EG and I have 2 tables:
Table1:
Id Item
1 A
1 B
1 C
2 B
2 D
3 C
3 E
3 F
Table2:
Id Item Amount
1 A 99
2 C 100
1 B 100
2 A 90
1 A 93
3 B 92
1 E 93
2 B 99
1 A 93
Now I would like to take the sum conditional for my table1 from table2 (when the ID and the Item match).
Id Item Want
1 A 285
1 B 100
1 C 0
2 B 99
2 D 0
3 C 0
3 E 0
3 F 0
So what am I supposed to do in SQL?
Thanks in advance.
Use a correlated subquery to SUM:
select t1.Id, t1.Item,
(select sum(t2.amount) from table2 t2 where t2.id = t1.id and t2.item = t1.item)
from table1 t1
This looks like aggregation to me, with a left join:
select t1.id, t1.item,
coalesce(sum(t2.amount), 0) as want
from table1 t1 left join
table2 t2
on t1.id = t2.id and t2.item = t2.item
group by t1.id, t1.item;

Sql query to get join of two tables and both table has where query

Stuck at join, tried left, right, left outer , right outer joins
table 1
selectionID name type
1 abc 1
2 def 1
3 ghi 2
4 dhi 2
5 gki 2
6 ppp 2
Table 2
TID UserID selectionID isOK
1 10 3 0
2 19 3 0
3 10 8 0
6 10 5 1
Desired result is
join of
select from table 1 where type =2
select from table 2 where UserID = 10
selectionID name type TID userID
3 ghi 2 1 10
4 dhi 2 undefined undefined/null
5 gki 2 undefined undefined/null
6 ppp 2 6 10
so basically i want all data from table 1 that fits in where clause and their respective data in table 2 with another where clause
As long as i have done research i need to use inner query of second table...am I going right way?
Try the following query:
SELECT t1.selectionID, t1.name, t1.type, t2.tid, t2.userID
FROM table1 t1 LEFT JOIN table2 t2 ON t1.type = t2.TID AND t2.userID = 10
WHERE t1.type = 2;
Stuck at join, tried left, right, left outer , right outer joins ... well LEFT JOIN is same as LEFT OUTER JOIN. BTW, you are looking for a LEFT JOIN probably like
select t1.selectionID,
t1.name,
t1.type,
t2.TID,
t2.UserId
from table1 t1
left join table2 t2 on t1.selectionID = t2.selectionID
and t2.UserId = 10
where t1.type = 2;
You were probably failing because placing the conditions in the where clause. If a row doesn't join you will have nulls in its columns, so a where condition will discard those rows
select *
from table1 t1
left join
table2 t2
on t1.selectionID = t2.selectionID and
t2.userID = 10
where t1.type = 2
Another way, is to force nulled rows to be accepted, using coalesce
select *
from table1 t1
left join
table2 t2
on t1.selectionID = t2.selectionID and
where t1.type = 2 and
coalesce(t2.userID, 10) = 10
select * from table1 t1
left join table2 t2 ON t1.SelectionID = t2.SelectionID
where t1.type = 2 AND t2.UserID = 10

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'

Joining multiple tables into one under one Id

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