SQL query for the below expected output - sql

I have 2 tables
TABLE1
ASSET OWNER1 OWNER2
-----------------------
note 111 444
pen 333 555
book 222 666
TABLE2
OWNER NAME
-------------
111 Avani
444 Jack
333 Jyothi
555 John
222 Nilehi
666 Mohit
What should be SQL query to get the following output?
ASSET OWNER1 NAME OWNER2 NAME
------------------------------------
note 111 Avani 444 Jack
pen 333 Jyothi 555 John
book 222 Nilehi 666 Mohit
I tried following query but the records of ASSET column are being repeated
SELECT DISTINCT(TABLE1.ARREST), TABLE1.OWNER1, TABLE2.NAME, TABLE1.OWNER2, TABLE2.NAME FROM TABLE1 JOIN TABLE2 ON
TABLE1.OWNER1 = TABLE2.OWNER OR TABLE1.OWNER2 = TABLE2.OWNER

Join the same table twice, with different aliases.
For example:
select
a.asset,
a.owner1,
b.name,
a.owner2,
c.name
from table1 a
left join table2 b on a.owner1 = b.owner
left join table2 c on a.owner2 = c.owner

You need two separate JOINs:
SELECT T1.ARREST, T1.OWNER1, T2_1.NAME, T1.OWNER2, T2_1.NAME
FROM TABLE1 T1 JOIN
TABLE2 T2_1
ON t1.OWNER1 = T2_1.OWNER JOIN
TABLE2 T2_2
ON T1.OWNER2 = T2_2.OWNER;
Often you would use LEFT JOINs for this, in case one of the columns is empty.

Related

How to create SQL query with two inner join's and an if case

I try co create a SQL query with two inner joins and an if case. I create an example to explain what I mean:
ID
Typ
Case
123
AAA
zzz
124
BBB
yyy
125
CCC
yyy
Typ1
ID1
AAA
888
BBB
999
CCC
777
ID2
Result
666
1
555
2
777
3
In words, the query should do:
Search in the first table for ID 125, so I get Typ CCC and Case yyy
If case is yyy then search in the second table for CCC in column Typ1, here I get the ID 777 and then search in the third table for 777 in column ID2 to get the result 3.
If case is not yyy then just show me the results of the first table.
The result should be:
ID
Typ
Result
123
AAA
No match
124
BBB
No match
125
CCC
3
I hope you can understand what I try to explain :)
You want to select data from the first table and only show data from the other tables where appropriate. So, outer join the other tables.
select t1.id, t1.typ, t3.result
from t1
left outer join t2 on t2.typ1 = t1.typ and t1.case = 'yyy'
left outer join t3 on t3.id2 = t2.id1
order by t1.id;

How to Join 3 tables based on 2 columns from one table in presto?

I Have 3 tables as below. In table1, if value in column id is present then join that column with other tables, if null I want to join with ref column from table 1 with other tables. What is the best way to do this
table1
Name id ref
abc 123
abc 456
edc 345 432
asd 678
table 2
city id ref
NY 123
WA 875
CA 345 432
SA 678
table 3
city orders
NY 78954
WA 123546
CA 789
SA 1
I want below result: ABC has 123 in id hence NY. ASD has 678, so considered ref column in table1 to join with other 2 tables
Name city order
ABC NY 78954
EDC CA 789
ASD SA 1
You can use left joins for this purpose:
select t1.*, t3.city, t3.count
from table1 t1 left join
table2 t2
on t1.id = t2.id left join
table2 t2r
on t1.ref = t2.ref and t1.id is null left join
table3 t3
on t3.city = coalesce(t1.city, t2.city);
Note: This returns all rows from table1, even those with no match in either column. If this is an issue, add:
where t2.id is not null or t2.ref is not null

How to count result values from join query in another table?

I have two tables like so:
table1(user, id, sex) table2(user, name, sex)
jjj 123 m jjj John m
jjj 124 m bbb Bob m
jjj 125 m ppp Pete f
bbb 126 m
bbb 127 f
ppp 128 f
ppp 129 m
ppp 130 m
I want result table where it displays all the users with their names and sex from table 2 who changed their sex at some point along with a count of how many users each name has. So this would be the result table:
(user, name, sex, count)
bbb Bob m 2
ppp Pete f 3
Currently im using this query:
select table2.user, table2.name, table2.sex, count(*)
from table1
join table2 on table1.user = table2.user
where table1.sex <> table2.sex
group by table2.user, table2.name, table2.sex
order by user
However the count column just counts from the resulting join table and not from original table1. Any ideas? thanks.
If I follow this correctly, one option use a lateral join and filtering:
select t2.*, t1.cnt
from table2 t2
inner join lateral (
select count(*) as cnt, min(sex) as minsex, max(sex) as maxsex
from table1 t1
where t1.user = t2.user
) t1 on t1.minsex <> t1.maxsex or t1.minsex <> t2.sex
Basically this filters table1 on users that have different sex or whose sex is different than in table2.

SQL - join tables on multiple columns

I want to join few tables:
table1:
A B_key B_version C D
123 abc 1 ccc 11
123 abc 2 ddd 11
456 dfg 1 rrr 22
789 vvv 1 55
table2:
A E F
123 s 5
456 r
111 t 2
table3:
B_key B_version G
abc 1 aa
abc 1 bb
abc 2 aa
abc 2 cc
dfg 1 aa
so the result would look like this:
A B_key B_version C D E F G
123 abc 1 ccc 11 s 5 aa
123 abc 1 ccc 11 s 5 bb
123 abc 2 ddd 11 s 5 aa
123 abc 2 ddd 11 s 5 cc
456 dfg 1 rrr 22 r aa
789 vvv 1 55
Version can go as high as 8.
IF I don't have A, B_key or B_version - the line is useless. Otherwise I need to keep all the information I do have.
In reality I have many more columns.
I've tried:
SELECT table1.A, table 1.B_key, table 1.B_version, table 1.C, table 1.D,
table2.E, table2.F,
table3.G
FROM table1
LEFT JOIN table2
ON table1.A = table2.A
LEFT JOIN table3
ON table1.B_key = table3.B_key AND
table1.B_version = table3.B_version
and the same with FULL JOIN.
It ends up the same: for every B_key only the highest B_version is kept, while the others disappear.
How can I avoid loosing information?
You can use left joins among tables as below :
select t1.A, t1.B_key, t1.B_version, t1.C, t1.D, t2.E, t2.F, t3.G
from table1 t1
left join table2 t2 on t2.A = t1.A
left join table3 t3 on t3.B_key = t1.B_key and t3.B_version = t1.B_version
Demo
in order to bring also the rows for unmatched values for join conditions.
If I understand correctly, you want all the b_keys and b_versions from table1 and table3. Then you want to bring in the other data. That suggests left joins
select . . .
from ((select B_key, B_version
from table1
) union -- on purpose to remove duplicates
( select B_key, B_version
from table3
)
) bb left join
table1 t1
on t1.b_key = bb.b_key and
t1.b_version = bb.b_version left join
table2 t2
on t2.a = t1.a left join
table3 t3
on t1.b_key = bb.b_key and
t1.b_version = bb.b_version;

How can I find duplicate records \ values after left join?

I have:
TABLE1 with ID, and Name.
TABLE2 with ID, and Address.
I want to get ALL TABLE1 records and add a STATUS column:
If this record exists in TABLE2 - 'OK'.
If this record is not exist in TABLE2, then research a match by last 2 digits, else 'NO_RECORD'.
If this record has duplicate records in TABLE2, then if the duplicate records has the same Address choose one record - 'OK', and if they doesn't has the same Address - 'DUPLICATE'.
Meanwhile, I've started with this:
SELECT t1.id,
t1.name,
t2.Address,
iif(Address is null, 'No_RECORD', 'Ok') as 'status'
FROM Table1 as t1
left join Table2 as t2 on t1.id = t2.id
For example:
Table1
id Name
111 aaa
222 bbb
333 ccc
444 ddd
555 eee
666 fff
777 ggg
888 hhh
999 iii
Table2:
id Address
111 rr
922 hfh
444 vbv
444 vbv
555 xxa
555 plo
555 plo
666 wqq
777 gyt
999 ree
999 ree
My accepted results are:
id name Address 'status'
111 aaa rr Ok
222 bbb hfh Ok
333 ccc No_RECORD
444 ddd vbv Ok
555 eee Duplicate
666 fff fff Ok
777 ggg wqq Ok
888 hhh No_RECORD
999 iii ree Ok
444 is not duplicate because the 2 table2's records address are match,
555 is duplicate because the 3 table2's records address are mismatch,
999 is not duplicate because the 2 table2's records address are match.
222 is ok because tha 2 last digits of it's id are exist in tabl2: "922".
How can I continue? (I use sql query in access).
I have no idea what "match by last five digits" is supposed to mean. It has nothing to do with your sample data, so I'm just ignoring that part of the question.
What you want to do is to aggregate on table2 before doing the join:
select t1.id, t1.name,
iif(multiple_addresses = 0, address, null) as address,
switch(t2.id is null, "No_Record",
multiple_addresses = 1, "Duplicate",
1=1, "OK"
) as status
from table1 as t1 left join
(select id, min(address) as address
iif(min(address) = max(address), min(address), 0, 1) as multiple_addresses
from table2
group by id
) as t2
on t1.id = t2.id;
You can use a case statement to get this status:
SELECT
t1.id,
t1.name,
t2.Address as add2,
case
when t2.Address is null and exists (select 1 from Table2 temp where temp.id = t1.id) then 'DUPLICATE'
when t2.Address is null then 'NO_RECORD'
else 'OK' end
as 'status'
FROM Table1 as t1
left join Table2 as t2 on t1.id = t2.id and t1.name = t2.Address
order by t1.id
As you can see I added and t1.name = t2.Address to the join clause to make sure you have non null Table2 values only when you want so.
About the case when, the first condition checks if 1) no corresponding record was found 2) there are records for the same id, meaning 'DUPLICATE'. The second condition checks that there are no corresponding record, and we already know there are no duplicates (as it would have fallen into the first case).
Working SQLFiddle.