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')
;
Related
say I have three tables: TableA, TableB, and TableC. Each of these tables have a column: ColA.
TableA is my main table and TableA.ColA has a value.
I wish to check either TableB or TableC has also a value in their ColA that corresponds with my TableA.ColA.
So my statement is:
select count(*)
from TableA, TableB, TableC
where ( TableA.ColA = TableB.ColA AND TableA.ColA = "ABC")
OR ( TableA.ColA = TableC.ColA AND TableA.ColA = "ABC" )
But this does not work.
If my TableB.ColA doesn't have a ColA value and TableC.ColA has a value, the result returned is still 0. I should get a count of 1 back.
What is wrong with my select statement?
My TableA data:
ColA
-----
ABC
My TableB data:
ColA
----
NULL
My TableC data:
ColA
----
ABC
Because TableC.ColA and TableA.ColA has the same value, it should return me a count of 1. But it is not doing so. My database is SAP ASE
thanks
You are doing INNER JOIN and you need OUTER JOIN or EXISTS. Syntax will vary for RDBMS you are using.
Try this:
SELECT COUNT(*)
FROM
TableA A
WHERE
A.ColA = "Value"
AND (
EXISTS(
SELECT * FROM TableB
WHERE
ColA = "Value"
)
OR EXISTS(
SELECT * FROM TableC
WHERE
ColA = "Value"
)
)
select count(*)
from TableA
LEFT JOIN
TableB
ON TableA.ColA = TableB.ColA
LEFT JOIN
TableC
ON TableA.ColA = TableC.ColA
where TableA.ColA = "Value"
AND
(TableB.ColA IS NOT NULL OR TableC.ColA IS NOT NULL)
The idea here is:
Use LEFT JOIN so that the row is generated whether or not TableB or TableC has a row for it. If one of them or both don't have it, corresponding values will be NULL
Filter out rows for which neither TableB nor TableC have those values by requiring that at least one of them is not NULL in the WHERE clause.
I'm trying to do a simple LEFT JOIN with tables with 2 IDs - basically an ID and Sub-ID. Each row has an ID, but not necessarily a Sub-ID. When a Sub-ID exists, I want to join based on that, if not join on the ID. I'd imagine something like
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON CASE WHEN SUB_ID IS NOT NULL THEN
a.SUB_ID = b.SUB_ID
ELSE
a.ID = b.ID END
AND
a.otherfield = b.otherfield
But I couldn't get anything like this to work, so instead I had to do 2 queries with a UNION (one that joined on SUB_ID WHERE SUB_ID IS NOT NULL and another that joined on ID WHERE SUB_ID IS NULL.) It worked but I can't imagine there isn't a way to do it. If it helps, my ID and SUB_ID values look like this:
ID SUB_ID
10000 NULL
10001 NULL
10001 10001-3
10001 10001-5
10014 NULL
Any suggestions on how to achieve this without doing a UNION? Thanks in advance!!
We can use COALESCE for this purpose:
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON COALESCE(a.SUB_ID,a.ID) = COALESCE(b.SUB_ID,b.ID)
COALESCE returns value of first not null parameter from left.
Here is the code at SQL Fiddle
This should work for you.
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON ((b.SUB_ID IS NOT NULL AND a.SUB_ID = b.SUB_ID) OR
(a.ID = b.ID))
AND a.otherfield = b.otherfield
Interesting.
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON (
a.SUB_ID = b.SUB_ID
OR (a.SUB_ID IS NULL AND b.SUB_ID IS NULL AND a.ID = b.ID)
)
AND a.otherfield = b.otherfield
That might well work. It's NOT going to be fast, though.
Depending on the state of your data and what you want to achieve, you might want to change the join clause to
ON (
a.SUB_ID = b.SUB_ID
OR (a.SUB_ID IS NULL AND a.ID = b.ID)
OR (b.SUB_ID IS NULL AND a.ID = b.ID)
)
AND a.otherfield = b.otherfield
... instead.
You could JOIN the table twice:
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON a.SUB_ID = b.SUB_ID
AND a.otherfield = b.otherfield
LEFT JOIN tablename c
ON a.ID = b.ID
AND a.SUB_ID IS NULL
AND a.otherfield = c.otherfield
Then use ISNULL to get the columns, e.g.
ColumnName = ISNULL(b.ColumnName, c.ColumnName)
It depends on your indexes, but I suspect this may get optimised better than having a conditional join clause.
Try something like this:
SELECT *
FROM TABLENAME A
LEFT JOIN TABLENAME B
ON (A.SUB_ID IS NOT NULL AND A.SUB_ID = B.SUB_ID)
OR (A.SUB_ID IS NULL AND A.ID = B.ID)
I have simple scenario but struggling at it:
Say I have following 2 tables:
tableA
Acol1 Acol2 Acol3
1 2 3
tableB
Bcol1 Bcol2 Bcol3
1 2 true
A query:
select tabB.Bcol3 from tableA tabA, tableB tabB
where
tabA.Acol1 = tabB.Bcol1
and tabB.Bcol2 = 1
and tabA.Acol1 = 1;
I want my query to return 'false' value since no record exists for this query.
P.S: I cannot user aggregate functions because actually this scenario is part of a larger query with around 15 joins and multiple columns.
So following solution is out of context:
select decode(max(tabB.Bcol3), null, 'FALSE', 'TRUE') from tableA tabA, tableB tabB
where
tabA.Acol1 = tabB.Bcol1
and tabB.Bcol2 = 1
and tabA.Acol1 = 1;
i tried left and right outer joins but in vain.
Use a LEFT JOIN with COALESCE():
select coalesce(tabB.Bcol3, false)
from tableA tabA
left join tableB tabB on tabA.Acol1 = tabB.Bcol2
and tabB.Bcol2 = 1
where tabA.Acol1 = 1;
COALESCE() returns the first non-null value. When the join fails to find a match, the columns of tableB will be null - that's when the default value of false will be returned.
It seems a little-known fact that join conditions may include non-key conditions. By including the extra condition on tabkeB in the join condition, the left join is still effective in returning a row for tableA. If left in the where clause, no row would be returned be ause the where clause is d listed after the join is made and would fail because a null is not going to equal 1.
I have a problem with a view I want to create. I have two tables joined in a left outer join, say tableA and tableB, where tableB is left outer joined.
I want to select only those rows from table B where state equals 4, so I add WHERE state = 4 to my query. Now the result set is trimmed quite a bit because all rows without a matching row in tableB are removed from the result (since state isn't 4 for those rows). I also tried WHERE state = 4 OR state IS NULL, doesn't work either (since state technically isn't NULL when there is no state).
So what I need is a WHERE statement which is only evaluated when there actually is a row, does such a thing exist?
If not I see two options: join (SELECT * FROM tableB WHERE state = 4) instead of table B, or create a view with the same WHERE statement and join that instead. What's the best option performance wise?
This is SQL Server 2008 R2 by the way.
You put the conditions in the on clause. Example:
select a.this, b.that
from TableA a
left join TableB b on b.id = a.id and b.State = 4
You can add state = 4 to the join condition.
select *
from T1
left outer join T2
on T1.T1ID = T2.T1ID and
T2.state = 4
Even easier than a subquery is expanding the on clause, like;
select *
from TableA a
left join
TableB b
on a.b_id = b.id
and b.state = 4
All rows from TableA will appear, and only those from TableB with state 4.
SQL Server will probably execute the view, expanded on, and subquery in exactly the same way. So performance wise, there should be little difference.
Alternative approach: (1) inner join to table B where state equals 4, (2) antijoin to table B to find rows that don't exist, (3) union the results:
SELECT A1.ID, A1.colA, B1.ColB
FROM tableA AS A1
INNER JOIN tableB AS B1
ON A1.ID = B1.ID
AND B1.state = 4
UNION
SELECT A1.ID, A1.colA, '{{MISSING}}' AS ColB
FROM tableA AS A1
WHERE NOT EXISTS (
SELECT *
FROM tableB AS B1
WHERE A1.ID = B1.ID
);
Alternatively:
SELECT A1.ID, A1.colA, B1.ColB
FROM tableA AS A1
JOIN tableB AS B1
ON A1.ID = B1.ID
AND B1.state = 4
UNION
SELECT ID, colA, '{{NA}}' AS ColB
FROM tableA
WHERE ID IN (
SELECT ID
FROM tableA
EXCEPT
SELECT ID
FROM tableB
);
How can you refer to the "combined entity" created from an outer join within your query? Specifically how can you replace the "??" in the query below:
SELECT TableA.x,
??.y --How do you select from the combined entity?
FROM TableA,
TableB buys
FULL OUTER JOIN TableB sells ON buys.run_id = sells.run_id
AND buys.specie_id = sells.specie_id
AND buys.account_id = sells.account_id
WHERE TableA.id = ??
AND -- want to join this with the "combined entity" resulting from the outer join
buys.buy = 'Y'
AND -- Is this valid or does this have to be within the Outer join statement?
sells.buy = 'N';
select TableA.x, fullTable.y
from TableA
INNER JOIN
( SELECT y
FROM TableB buys
full outer join TableB sells
on buys.run_id = sells.run_id
and buys.specie_id = sells.specie_id
and buys.account_id = sells.account_id
AND buys.buy = 'Y' AND sells.buy = 'N'
) AS fullTable
ON TableA.id = fullTable.y
The condition can be in the final WHERE or ON like this but it essentially cancels the full join:
select TableA.x, fullTable.y
from TableA
INNER JOIN
( SELECT y
, buys.buy AS buysBuy --- fields here so they can be
, sells.buy AS sellsBuy --- used in the final WHERE or ON
FROM TableB buys
full outer join TableB sells
on buys.run_id = sells.run_id
and buys.specie_id = sells.specie_id
and buys.account_id = sells.account_id
) AS fullTable
ON TableA.id = fullTable.y
AND buysBuy = 'Y' AND sellsBuy = 'N' --- the condition here
Presumably what you're trying to ask is how to refer to the columns used in the join in other parts of the query. There is no joined entity per se; you still have to refer to the columns from the tables (in this case "buys" or "sells", it just happens that the columns used in the join will have the same value for both tables.
If you want whichever is not null (since this is a full outer join), you can use coalesce or nvl to find find the non-null value:
SELECT TableA.x,
nvl(buys.run_id,sells.run_id) as run_id,
...
You need the sells.buy = 'N' and buys.buy = 'Y' predicates inside the outer join.
SELECT TableA.x,
??.y --How do you select from the combined entity?
FROM TableA,
INNER JOIN TableB buys ON <whatever>
AND buys.buy = 'Y'
FULL OUTER JOIN TableB sells ON buys.run_id = sells.run_id
AND buys.specie_id = sells.specie_id
AND buys.account_id = sells.account_id
AND sells.buy = 'N'
As for ??.y, you need to specify whichever table you want it from - TableA, buy or sell.