SQL Server - Inner Join On - Conditional Statement - sql

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)

Related

Unable to apply case statement in join condition

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
)

Where not in inner join function

So I'm trying to fetch data from my database with an inner join function and I'm trying to use where not on it.
This is my query:
SELECT DISTINCT a.*
FROM students AS a
INNER JOIN messages AS b ON a.id = b.from_id OR b.to_id
WHERE (from_id = a.id AND to_id = 1)
OR (from_id = 1 AND to_id = a.id)
AND a.status = 1
AND NOT a.id = 30
It works fine but the row with id = 30 on students table is still getting selected
Here is the query you need:
You need to change your inner join condition to ON a.id = b.from_id OR a.id = b.to_id
You need to add new parentheses for first where condition like this: WHERE ((from_id = a.id AND to_id = 1) OR (from_id = 1 AND to_id = a.id))
SELECT DISTINCT a.*
FROM students a
INNER JOIN messages b ON a.id = b.from_id OR a.id = b.to_id
WHERE ((from_id = a.id AND to_id = 1) OR (from_id = 1 AND to_id = a.id))
AND a.status = 1
AND not a.id = 30
And here is a small demo on SQLServer(maybe that is your database):
DEMO
Try to add additional parentheses to group 'OR' condition
WHERE ((from_id = a.id AND to_id = 1) OR (from_id = 1 AND to_id = a.id))
AND a.status = 1
AND NOT a.id = 30
SELECT DISTINCT a.* FROM students AS a
INNER JOIN messages AS b
(ON a.id = b.from_id)
OR
(ON a.id = b.to_id)
WHERE
(from_id = a.id AND to_id = 1)
OR (from_id = 1 AND to_id = a.id)
AND a.status = 1
AND NOT a.id = 30
You should add proper () around the OR condition in join and in where
SELECT DISTINCT a.*
FROM students AS a
INNER JOIN messages AS b ON a.id = ( b.from_id OR b.to_id )
WHERE ((b.from_id = a.id AND b.to_id = 1) OR (from_id = 1 AND to_id = a.id) )
AND a.status = 1
AND NOT a.id = 30
SELECT DISTINCT incurs overhead to remove duplicates. That is unnecessary if you use EXISTS:
SELECT s.*
FROM students s
WHERE EXISTS (SELECT 1
FROM messages m
WHERE ( (s.id = m.from_id AND m.to_id = 1) OR
(s.id = m.to_id AND m.from_id = 1)
) AND
m.status = 1 AND
m.id <> 30
);
Of course, the right parentheses are still needed.
Note two other changes:
The table aliases are abbreviations for the table names, rather than arbitrary letters. This makes the query easier to understand, modify, and maintain.
<> is the SQL standard operator for "not equals". Of course, NOT m.id = 30 works, but it is not colloquial.

ORA-01427: single-row subquery returns more than one row error | But I want multiple values

I've below query, into which I'm creating using a subquery which is returning
ORA-01427: single-row subquery returns more than one-row error.
But I want all the values that subquery is returning, and there is no other column left for the join condition. Below is my sample query.
select name,
dob,
cdate,
(select value
from item a,
books b
where a.id = b.id
and a.newid = b.newid
and a.id = s.id
and a.bid = s.cid
and a.eventid=1) col_value,
(select value2
from item a,
books b
where a.id = b.id
and a.newid = b.newid
and a.id = s.id
and a.bid = s.cid
and a.eventid=1) col_value2
from sample s,
purchase p
where s.id = p.id
and s.cid = p.cid
Desired Output
Do I need to apply a Group By? Please let me know your suggestions.
It is little bit more difficult without data but try:
select name -- please use table alias so you know which table the value is from (s, p or cv)
, dob
, cdate
, cv.value
from sample s
left join purchase p on s.id=p.id and s.cid=p.cid --or just join
left join (select value, a.id, a.bid --or just join
from item a
left join books b --or just join
on a.id=b.id and a.newid=b.newid) cv
on cv.id = s.id and cv.bid = s.cid
left join (select value2
from item a
left join books b
on a.id = b.id and a.newid = b.newid) cv2
on cv2.id = s.id and cv2.bid = s.cid
where cv2.eventid=1;
select name,
dob,
cdate,
(select value
from
books b
where a.id = b.id
and a.newid = b.newid ) col_value,
(select value2
from
books b
where a.id = b.id
and a.newid = b.newid ) col_value2
from sample s,
purchase p,item a
where s.id = p.id
and s.cid = p.cid
and a.id(+)=s.id
and a.bid(+)=s.cid
and a.eventid(+)=1

What does a = b = c mean in sql?

I see that it's possible to compose a query in vertica SQL where you compare between 3 parameters in the below way
select * from table1 a
join table2 b on ...
join table3 c on ...
where a.id = b.id = c.id
Is it equal to
select * from table1 a
join table2 b on ...
join table3 c on ...
where a.id = b.id and b.id = c.id
Or does it have a different meaning?
b.id = c.id will be evaluated first, and be equal to true or false.
This will then be compared to a.id, which can be boolean or a number equal to 0 or 1. If a.id is a number other than 0 or 1, you will get an error.
That been said, I think that's not the behavior you want :)

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