SQL join with case - sql

How can I modify the join clause with a case clause; for example I want the table to join another column if column1 is null such as:
SELECT * FROM MYTABLE
LEFT JOIN OTHERTABLE ON
CASE WHEN MYTABLE.A IS NULL THEN MYTABLE.B = OTHERTABLE.A
ELSE MYTABLE.A IS NOT NULL THEN MYTABLE.A = OTHERTABLE.A
(totally made that up,sorry for syntax errors :))

Try this one:
SELECT *
FROM MyTable M
LEFT JOIN OtherTable O ON(CASE WHEN M.A IS NULL THEN M.B ELSE M.A END) = O.A

SELECT * FROM MYTABLE
LEFT JOIN OTHERTABLE ON COALESCE(MYTABLE.A, MYTABLE.B) = OTHERTABLE.A

Just try below code :
SELECT * FROM MYTABLE
LEFT JOIN OTHERTABLE ON OTHERTABLE.A = isnull(MYTABLE.A,MYTABLE.B)

You can use isnull() or coalesce() to check the null value.

Related

Conditionally joining from multiple tables

Does SQL allow some form of conditional "table choosing" within the Join statement? ie. selecting a different table to join based on a predefined variable/condition.
define var = 1
select *
from tbl
join (case when &var=1 then tblA when &var=2 then tblB else tblC end) a on tbl.id = a.id
The error I get when attempting this method is ORA-00905: missing keyword.
No. Neither SQL nor Oracle allow this, unless you use dynamic SQL.
Assuming the tables have the same columns, you could write this logic as:
select *
from tbl join
(select a.* from tblA where &var = 1 union all
select b.* from tblB where &var = 2 union all
select c.* from tblC where &var not in (1, 2)
) abc
on tbl.id = abc.id;
You still need to specify all joins ahead of time and they would have to be left outer joins, but you can rewrite your statement like this. This way will work regardless of the number of fields in each of the tables (requirement for the union), and if they are named differently then you can access the appropriate field by name.
DECLARE #var int
SET #var=1
select tbl.*, tblA.ShippingName, tblB.BillingName, tblC.OtherName
from tbl
left outer join tblA on tbl.id = tblA.id and #var = 1
left outer join tblB on tbl.id = tblB.id and #var = 2
left outer join tblC on tbl.id = tblC.id and #var = 3

Cancel join condition based on column value

I am stuck into a situation where I need to perform conditional join. The brief summary could be, I have 2 tables TableA and TableB.
TableA has columns A1,A2,A3,A4,A5,Condition1,Condition2
similarly TableB has columns B1,B2,Condition1,Condition2
And I need to perform join on TableA.Condition1 = TableB.Condition1 and condition join on TableA.Condition2 = TableB.Condition2, condition being TableA.Condition2 should not be null for any record first join.
In other words, if I some any record with TableA.Condition1 = TableB.Condition1 matched and at the same time TableA.Condition2 is not null for any of them then perform second join, otherwise don't perform second join.
Query could be like
SELECT A.* FROM TableA A
INNER JOIN TableB B
ON A.Condition1 = B.Condition1 -- This must be perform
AND WHEN A.Condition2 IS NULL THEN
1 = 1 -- Assuming no join here
ELSE
A.Condition2 = B.Condition2 -- perform join
END
You are only selecting from TableA, so how about using exists instead?
SELECT A.*
FROM TableA A
WHERE (A.Condition2 IS NULL AND
EXISTS (SELECT 1 FROM TableB b WHERE A.Condition1 = B.Condition1)
) AND
(A.Condition2 IS NOT NULL AND
EXISTS (SELECT 1 FROM TableB b WHERE A.Condition1 = B.Condition1 AND A.Condition2 = B.Condition2)
);
Or, if you want a JOIN:
SELECT A.*
FROM TableA A JOIN
TableB B
ON A.Condition1 = B.Condition1 AND
(A.Condition2 IS NOT NULL OR A.Condition2 = B.Condition2);
Try this may help you
SELECT A.*
FROM TableA A
INNER JOIN TableB B ON A.Condition1 = B.Condition1 AND
((A.Condition2 IS NOT NULL AND A.Condition2 = B.Condition2)
OR (A.Condition2 IS NULL) )
hard to understand your question and even harder to understand the purpose
SELECT A.*
-- join table1 and table2 on Condition1
FROM TableA A
JOIN TableB B ON A.Condition1 = B.Condition1
-- if max condition2 is null then there is nothing but nulls
JOIN ( SELECT MAX(Condition2) Condition2 FROM TableA A2 ) A2
-- in that case every row resulting from join1 goes
ON A2.Condition2 IS NULL
-- otherwise use condition2 but replace nulls with some placeholder
-- or maybe you have either all null or no nulls
OR COALESCE (A.Condition2,'null') = COALESCE (B.Condition2,'null')
;

Left join to same table SQL

I am trying to make a left join to the same table in the same query but the result is not okey, I resolved the problem with a subquery this is the wrong query:
SELECT * FROM TableA ta
LEFT JOIN TableA Lta ON ta.key = Lta.key
AND ta.state IN('C')
AND Lta.state IN ('A','E')
WHERE Lta.key is null
This is the way how I resolved
SELECT * FROM (
SELECT * FROM TableA ta
WHERE ta.state IN('C')
) AS T LEFT JOIN TableA Lta ON T.key = Lta.key
AND Lta.state in ('A','E')
WHERE Lta.key IS NULL
I am a little confused with those queries if you can give me some information related to this topic I will be so grateful to you
Thank you
You were very close in your first query. Move the "ta.state" to the where clause. The join is how the two tables relate but secondary criteria on JUST the "lta" alias.
SELECT
*
FROM
TableA ta
LEFT JOIN TableA Lta
ON ta.key = Lta.key
AND Lta.state IN ('A','E')
WHERE
ta.state IN('C')
AND Lta.key is null
So your primary criteria is WHERE the ta.state is "C", but then only if there is NOT a match for the "A" and "E" instances in the second (left-join) alias of lta
For "not-existance" checking case I strongly recommend you to use not exists subquery:
SELECT * FROM TableA ta
WHERE not exists
(
SELECT 1 FROM TableA Lta
WHERE ta.key = Lta.key
AND ta.state IN('C')
AND Lta.state IN ('A','E')
)
this is the most performance-friendly approach.
Not sure but it's likely that you should move ta.state = 'C' to the outer where clause.

How to update table using select statement results in sql server

I am trying to update a tabel where the value of field is equal the result of select statement. I have a table like this:
Type Total#
A 4
B 8
C 1
I want to update the above table based the result of a select statement.
Here is my code:
update MainTable
set [Total#] =
(SELECT count(distinct r.[ID])as Type
FROM dbo.TableA r left join
dbo.TableB a
on r.Post_ID = a.Post_ID
where a.Status is null)
if i run the code as is, it is going to update all rows but i only want to update where Type from select statement is equal the Type from my MainTable. thanks
Give this a try,
UPDATE x
SET x.[Total#] = y.totalCount
FROM MainTable x
INNER JOIN
(
SELECT [Type], COUNT(DISTINCT r.[ID]) totalCount
FROM dbo.TableA r
LEFT JOIN dbo.TableB a
ON r.Post_ID = a.Post_ID
WHERE a.STATUS IS NULL
GROUP BY [Type]
) y ON x.[Type] = y.[Type]
PS: when asking question like this, please add the structure of the table. It helps a lot.
Give an alias to your MainTable and you can use it in the subquery:
update MainTable mt
set [Total#] = (SELECT count(distinct r.[ID]) as Type
FROM dbo.TableA r
left join dbo.TableB a on r.Post_ID = a.Post_ID
where a.Status is null
and a.AType = mt.AType )
where mt.AType = #Value

postgres: use of CASE and ANY() in WHERE clause

Is there some way to make this work?
SELECT
*
FROM table t
INNER JOIN othertable t2 USING (tid)
WHERE
t.tid =
CASE
WHEN t2.someboolval THEN ANY(ARRAY[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16])
ELSE ANY(ARRAY[77,66])
END
Unfortunately I can't just do t.tid = CASE WHEN t2.someboolval THEN 1 ELSE 2 END because I need to match against an array. Is this doable?
Use AND/OR. Something like:
SELECT
*
FROM table t
INNER JOIN othertable t2 USING (tid)
WHERE
t2.someboolval AND t.tid IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
OR NOT (t2.someboolval) and t.id IN (77,66)
Edit: formatted
You have to change place of ANY:
SELECT
*
FROM table t
INNER JOIN othertable t2 USING (tid)
WHERE
t.tid =
ANY(CASE
WHEN t2.someboolval THEN ARRAY[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
ELSE ARRAY[77,66]
END)