Sql oracle left join only match single rows - sql

I need short sql to left join T2 on T1 only if single math
T1 T2 Desired
F1 F2 F1 F2 F1 F2
1 A A RR 1
2 B A 2 UU
3 C A TT 3
4 D B UU 4 YY
5 E C VV 5 ZZ
C XX
D YY
E ZZ

You could use a simple GROUP BY/COUNT to count the rows per hit and a CASE expression to only output the value if the row count is <=1;
SELECT T1.F1, CASE WHEN COUNT(*)>1 THEN NULL ELSE MAX(T2.F2) END F2
FROM T1
LEFT JOIN T2 ON T1.F2 = T2.F1
GROUP BY T1.F1
An SQLfiddle to test with.

USING group by to eliminate the records with duplicates and doing left join to get all values from T1
select T1.F1, ISNULL(T2.F2,'') from T1
LEFT JOIN
(
select F1 from T2
group by F1
having count(*) =1
) T
on T1.F1 = T.F1
LEFT JOIN T2
on T2.F1 = T.F1

Related

How to join on a default value from the 2nd table if no match is found?

I'm looking for a way to join 2 tables as follows:
T1: T2:
a b c d e
------- -------------
1 b1 1 d1 e1
2 b2 2 d2 e2
3 b3 ST d0 e0
--> join on T1.a = T2.c (if no match found join on T1.c = ST)
a b c d e
----------------------
1 b1 1 d1 e1
2 b2 2 b2 e2
3 b3 ST d0 e0 <- No match found so ST values are used.
Right now I only found a way when T2.c are integers. I do a conditional join en afterwards i take the max value of c en group by every other column.
Is there any way to do this with string values like in the example in the match column?
Thanks
You want a default. You can use left join:
select t1.*, coalesce(t2.c, t2def.c) as c,
coalesce(t2.d, t2def.d) as d, coalesce(t2.e, t2def.e) as e
from t1 left join
t2
on t1.a = t2.c left join
t2 t2def
on t2def.c = 'ST';
Or, you can use apply:
select t1.*, t2.*
from t1 outer apply
(select top (1) t2.*
from t2
where t2.c in ('ST', t1.a)
order by (case when t2.c = 'ST' then 2 else 1 end)
) t2;

Removing string from sql

Please see below data..
Table A
AID NAME
1 A
2 B
3 C
4 D
5 E
6 F
Table B
BID AID NAME
1 1 T1
2 1 T2
3 2 T3
4 2 T4
5 3 T5
6 4 T6
7 1 T7
8 1 T8
9 2 T9
10 2 T10
11 3 T11
12 4 T12
I am using this statement
SELECT
dbo.A.NAME AS ANAME, dbo.B.NAME AS BNAME
FROM
dbo.A
LEFT OUTER JOIN
dbo.B ON dbo.A.AID = dbo.B.AID
Its returning these results:
ANAME BNAME
A T1
A T2
A T7
A T8
B T3
B T4
B T9
B T10
C T5
C T11
D T6
D T12
E NULL
F NULL
but I need following result
ANAME BNAME
A T1
T2
T7
T8
B T3
T4
T9
T10
C T5
T11
D T6
T12
E NULL
F NULL
How to remove extra names from above?
Try this
SELECT CASE WHEN ROW_NUMBER() OVER ( PARTITION BY A.NAME ORDER BY A.NAME ) = 1
THEN A.NAME
ELSE ''
END AS ANAME ,
dbo.B.NAME AS BNAME
FROM dbo.A
LEFT OUTER JOIN dbo.B ON dbo.A.AID = dbo.B.AID;
I guess something like the following could be done if absolutely needed to do in SQL, seeing as it is presentation.
SELECT CASE WHEN ROW_NUMBER() OVER ( PARTITION BY A.AID ORDER BY A.AID ) > 1
THEN ''
ELSE A.NAME
END AS ANAME ,
dbo.B.NAME AS BNAME
FROM dbo.A
LEFT OUTER JOIN dbo.B ON dbo.A.AID = dbo.B.AID;
You can use below SQL query to get your desired output:
SELECT (CASE WHEN SrNo = 1
THEN ANAME
ELSE ''
END) AS ANAME
, BNAME
FROM (
SELECT ROW_NUMBER OVER (PARTITION BY dbo.A.NAME ORDER BY dbo.B.NAME) AS SrNo,
dbo.A.NAME AS ANAME, dbo.B.NAME AS BNAME
FROM dbo.A LEFT OUTER JOIN
dbo.B ON dbo.A.AID = dbo.B.AID
) AS tbl

Returning Unique rows from Left Outer Join

I am trying to build a query which will give me unique rows. Details:-
Table 1 (F1, F2 are the columns)
F1 F2
1 A1
2 A2
3 A3
4 A4
Table 2 (F3,F4 are the columns)
F3 F4
1 B1
1 B11
2 B2
2 B22
My Query (Incorrect)
select rrn(A), F1,F2,F3,F4 from rush2hem1.T1 A left outer join rush2hem1.T2 B on A.F1=B.F3
This gives me below output which is not what I am looking for:-
RRN F1 F2 F3 F4
1 1 A1 1 B1
1 1 A1 1 B11
2 2 A2 2 B2
2 2 A2 2 B22
3 3 A3 (null) (null)
4 4 A4 (null) (null)
Expected output that I am building query for is:-
RRN F1 F2 F3 F4
1 1 A1 1 B1
2 2 A2 2 B2
3 3 A3 (null) (null)
4 4 A4 (null) (null)
Please let me know if you have any suggestions.
This problem could be solved differently in different RDBMS. In any case, you have to specify which one record from Table2 do you want to get (by order by clause)
If your database have window function row_number(), you can use it like this:
select
F1, F2, F3, F4
from (
select
T1.F1, T1.F2, T2.F3, T2.F4,
-- order by specifying which row you would get from Table2
row_number() over(partition by T1.F1 order by T2.F4) as rn
from Table1 as T1
left outer join Table2 as T2 on T2.F3 = T1.F1
) as cte
where rn = 1;
In SQL Server, you can use outer apply:
select
T1.F1, T1.F2, T2.F3, T2.F4
from Table1 as T1
outer apply (
select top 1 T2.F3, T2.F4
from Table2 as T2
where T2.F3 = T1.F1
order by T2.F3 asc -- This is important line
) as T2;
In PostgreSQL, you can use distinct on syntax:
select distinct on (T1.F1)
T1.F1, T1.F2, T2.F3, T2.F4
from Table1 as T1
left outer join Table2 as T2 on T2.F3 = T1.F1
order by T1.F1, T2.F4; -- sort by F4 is important
SQL Server sqlfiddle demo
PostgreSQL sqlfiddle demo
Not tested, It's a SQL server version.
select rrn(A), F1,F2,F3,F4
from
(
select rrn(A), F1,F2,F3,F4,row_number() over(partition by RRN order by RRN) as rn
from rush2hem1.T1 A left outer join rush2hem1.T2 B
on A.F1=B.F3
) as dt
where dt.rn = 1
Please check the result with OUTER APPLY
SELECT
*
FROM
Table1 a
OUTER APPLY
(SELECT
TOP 1 *
FROM
Table2 b
WHERE a.F1=b.F3)c

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.

How to do distinct by first column

Select DISTINCT wpg.ID as id1,wr.ID as id2
FROM Table1 wpg
inner join Table2 wp ON wp.WpgId = wpg.ID
inner join Table3 wr ON wr.WpId = wp.ID
I need wpg.Id distinct how do this?
I need from:
1 2
2 3
1 4
get:
1 2
2 3
The answer depends on what you want to do with the second column. I'm assuming you want the smallest value:
select
wpg.ID as id1,
min(wr.ID) as id2
from
Table1 wpg
inner join Table2 wp on wp.WpgId = wpg.ID
inner join Table3 wr on wr.WpId = wp.ID
group by
wpg.ID
select wpg.ID, min(wr.ID)
FROM Table1 wpg
inner join Table2 wp ON wp.WpgId = wpg.ID
inner join Table3 wr ON wr.WpId = wp.ID
group by wpg.ID