Unable to apply case statement in join condition - sql

I have two tables TableA and TableB. For one of the record in TableB(id =1), I want to perform join on condition1(a.value = b.value) and for other records I want to join on condition2((a.value - b.value)/ a.val < 1).
But, I am getting syntax error at end. How to apply case condition in this scenario?
Select * from TableA a
LEFT JOIN TableB b
on a.id = b.id
and (
case when b.id = 1 then a.value = b.value
else (a.value - b.value)/ a.val < 1 end
)

Just use boolean logic:
select *
from TableA a left join
TableB b
on a.id = b.id and
(b.id = 1 and a.value = b.value or
b.id <> 1 and (a.value - b.value)/ a.val < 1
)

Related

SQL query to select from one table based on a column value in other table

I have two tables and I want to select all values from "TABLE A" that have a different value in a column from "TABLE B".
I tried this
SELECT A.* FROM tableA A
left join tableB B ON A.id = B.id WHERE B.column <> 1;
But this just return the value that I want to ignore.
SELECT A.*
FROM tableA A
INNER JOIN tableB B
ON A.id = B.id
WHERE B.column != 1;
or
SELECT A.* FROM tableA A WHERE A.Id NOT IN (SELECT B.Id FROM tableB B WHERE B.column != 1)
Depends on your SQL you can use <> or !=
I would suggest not exists:
SELECT A.*
FROM tableA A
WHERE NOT EXISTS (SELECT 1 FROM tableB B WHERE A.id = B.id AND B.column = 1);
Using a JOIN can result in duplicated rows, if more than one row in B matches the JOIN condition.

Combine two sql queries into a single table

I have two SQL queries where uses an inner join first to match based on a condition, and the other does not. Ultimately, I would like the difference between the columns created by each query. How can I do this?
I have tried unioning and joining the queries as in some similar posts, but it won't work. I wonder if the issue is around the joins within each query.
Query 1 :
SELECT A.date, COUNT(DISTINCT A.id)
FROM A
INNER JOIN B
ON A.id = B.id AND A.date = B.date
AND B.col1 = 'value1'
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2'
AND C.category = 'cat1'
GROUP BY 1
ORDER BY 1 DESC
Query 2 :
SELECT A.date, COUNT(DISTINCT A.id)
FROM A
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2'
AND C.category = 'cat1'
GROUP BY 1
ORDER BY 1 DESC
Your left join of c is actually turned to an inner join because it's used in a NULL excluding expression in the WHERE clause. So you can directly inner join c and left join b. Then you can use a case in one count() to count only the instances where a row from b was joined. Subtract that value from another count() counting all occurrences to get difference.
SELECT a.date,
count(DISTINCT a.id)
-
count(DISTINCT CASE
WHEN b.id IS NOT NULL THEN
a.id
END)
FROM a
INNER JOIN c
ON c.key = a.key
AND c.category = 'cat1'
LEFT JOIN b
ON a.id = b.id
AND a.date = b.date
AND b.col1 = 'value1'
WHERE a.col1 = 'value2'
GROUP BY 1
ORDER BY 1 DESC;
SELECT A.date, COUNT(DISTINCT A.id)
FROM A
INNER JOIN B
ON A.id = B.id AND A.date = B.date
AND B.col1 = 'value1'
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2'
AND C.category = 'cat1'
GROUP BY 1
ORDER BY 1 DESC
UNION
SELECT A.date, COUNT(DISTINCT A.id)
FROM A
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2'
AND C.category = 'cat1'
GROUP BY 1
ORDER BY 1 DESC
A simple way is to JOIN the two queries, using the date column, which is available in both queries :
SELECT x.date, x.cnt, y.cnt, y.cnt - x.cnt
FROM
(
SELECT A.date, COUNT(DISTINCT A.id) AS cnt
FROM A
INNER JOIN B ON A.id = B.id AND A.date = B.date AND B.col1 = 'value1'
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2' AND C.category = 'cat1'
GROUP BY 1
) AS x
INNER JOIN (
SELECT A.date, COUNT(DISTINCT A.id) AS cnt
FROM A
LEFT JOIN C on C.key = A.key
WHERE A.col1 = 'value2' AND C.category = 'cat1'
GROUP BY 1
) AS y ON x.date = y.date
ORDER BY 1 DESC
You might want to adapt the join type according to your data layout :
LEFT JOIN if all dates are available in the first subquery but may be missing in the second subquery
RIGHT JOIN if the situation is the other way around
FULL OUTER JOIN if you want all available dates from both ends
If you choose any of the above option, you would need to use COALESCE to prevent the substraction to return NULL when one of the terms is NULL.

return pair of values instead of one value from two queries

I've got two queries that return single result.
They look something like this
// query 1
SELECT A.id FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
// query 2
SELECT C.id FROM tableC C
WHERE c.status = 'ACTIVE'
How to combine them and make return the pair of values instead of one value from different queries? I mean to get something like [A.id, C.id]
Currently I have to use two queries in the applications and I want to combine them into one.
I think like this will do
SELECT (SELECT A.id FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
) as 'query1',
(
SELECT C.id FROM tableC C
WHERE c.status = 'ACTIVE'
) as 'query2'
As your question is not clear, so i assume that you either needids from mentioned queries in one row or in different rows, you can use union all/union (provided that datatypes are compatible or implicitly convertible and duplicates or allowed or not) as below.
Combining Result in different rows.
SELECT A.id
FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
union all
SELECT C.id
FROM tableC C
WHERE c.status = 'ACTIVE'
Combining Result in Single Row.
select max(id1), max(id2)
from(
SELECT A.id as id1, NULL as id2
FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
union all
SELECT NULL, C.id
FROM tableC C
WHERE c.status = 'ACTIVE'
) t;
SAMPLE DEMO
You can run following query which work fine for me:
select t1.id as aid ,t2.id as cid
from (
SELECT A.id
FROM tableA A
INNER JOIN tableB B ON B.id = A.id
WHERE b.status = 'ACTIVE'
) t1
full outer join (
SELECT C.id
FROM tableC C
WHERE c.status = 'ACTIVE'
) t2 on t1.id=t2.id
You can join your second query with your first query as follows, so that you will get two (A.id, C.id) values in one query...
SELECT A.ID,C.ID FROM
(SELECT A.ID FROM table_A A INNER JOIN
table_B B ON A.ID=B.ID WHERE B.STATUS='A')A
INNER JOIN table_c C
ON C.ID=A.ID WHERE C.STATUS='A';

Case in SQL join statement

I have to use a conditional statement in join:
select * from A inner join B
on A.id = B.id
if B.id is null or B.id = '' or A.id is null or A.id = '' it should be A.name = B.name, instead of A.id = B.id
I have to use a conditional statement in join:
select * from A inner join B
on A.id = B.id
if B.id is null or B.id = '' it should be A.id2 = B.id2 instead of A.id = B.id.
Is it correct if I do something like this:
select *
from A inner join B on
(B.id is not null and B.id <> '' and A.id is not null and A.id <> '' and A.id = B.id) or
((B.id is null or B.id = '' or A.id is null or A.id = '') and A.name = B.name)
I think you will want something like this:
select * from A
inner join Bid on
(Bid.id is not null and Bid.id <> '' and A.id is not null and A.id <> '' and A.id = Bid.id)
inner join Bname on
((Bname.id is null or Bname.id = '' or A.id is null or A.id = '') and A.name = Bname.name)
that is to join on the B table twice, one join for when id is not null and the second join when id is null and you join on the name column instead. This works effectively like a case statement because the two joins to the B table are mutually exclusive.
Try this
select * from A inner join B
on (A.id = B.id) or
(A.name = B.name and (B.id is null or B.id = '' or A.id is null or A.id = ''))
try this code
DECLARE #b varchar(50)=(SELECT id FROM b)
DECLARE #a varchar(50)=(SELECT id FROM a)
if ((#b in (null , '')) and (#a in (null , '')))
BEGIN
select * from A inner join B
on
A.name = B.name
END
else
BEGIN
select * from A inner join B
on A.id = B.id
END

SQL Server - Inner Join On - Conditional Statement

I am using SQL Server 2008 and have the following scenario:
I have Table a with fields id and groupId.
I have Table b with fields id and groupId also.
The rule in Table b, is that:
If a.id = 0, then a.groupId = b.groupId
Else a.id = b.id (in which case a.groupId = 0)
The 2 tables are also linked by agrId such that a.agrId = b.agrId
How can I join these tables, whilst satisfying the rule above?
Update: Apologies for the lack of clarity, I have updated the rule and added my attempt below:
select * from a
inner join b
on a.agrId = b.agrId
where (
(b.id > '0' and b.groupId = '0')
or
(b.groupId > '0' and b.id = '0')
)
Try this
SELECT *
FROM TableA A
INNER JOIN TableB B
ON (B.ID = 0 AND A.groupId = B.groupId)
OR (B.groupId = 0 AND A.id = B.id)
Al it needs is an expression that evaluates to true or false, to indicate if these two rows should be joined. So based on what you say, this would be the join condition:
select *
from tA a
inner join tB b
on (a.id = 0 and a.groupid = b.groupid)
or (a.groupid = 0 and a.id = b.id)
Try this:
SELECT *
FROM a INNER JOIN
b ON a.agrId = b.agrId
WHERE (b.id = '0' AND b.groupId = a.groupId)
or
(b.groupId = '0' AND b.id = b.id)