Trouble with a conditional join - sql

I'm trying to join depending on whether table1.column1 is null or not null.
For, example I have two tables, table1 and table2, and the query:
SELECT
A.column2
FROM table1 A , table2 B
WHERE if A.column1 is not null then (A.column1=B.column1)
else if A.column1 is null then (A.column3 = B.column1);

Try this:
SELECT
A.column2
FROM table1 A
JOIN table2 B ON
B.column1 = A.column1 OR
(A.column1 IS NULL AND B.column1 = A.column3)
Note that B.column1 = A.column1 will never be true if either B.column1 or A.column1 is NULL.

Try this...
SELECT A.column2
FROM table1 A
JOIN table2 B ON NVL(A.column1, A.column3) = b.Column1
If b.Column1 can also be null, and you want to compare two null columns, you can try this...
SELECT A.column2
FROM table1 A
JOIN table2 B ON NVL(b.Column1, 'X') = COALESCE(A.column1, A.column3, 'X')
Assuming b.Column1 can never have the value 'X'

Related

Anti Join based on multiple keys / columns (SQL)

The setting is simple, I wanted to retrieve all rows from table A that were not present in table B. Because a unique row can be identified using 4 columns, I needed to have a way to write the WHERE statement that it works correctly.
My solution is to concatenate the 4 columns and use that as "one" column/key to do the outer join:
select *
from table_A
where filter_condition = 0
and (column1 || column2 || column3 || column4) not in (
select A.column1 || A.column2 || A.column3 || A.column4
from table_A A -- 1618727
inner join table_B B
on A.column1 = B.column1
and A.column2 = B.column2
and A.column3 = B.column3
and A.column4 = B.column4
and filter_condition = 0
)
My question is, is this a good way of doing this or am I doing something fundamentally wrong?
To be clear, the desired result is simply to get back only the rows of table_A that I "lose" due to the INNER JOIN with table_A and table_B.
You seem to be looking for not exists:
select a.*
from table_a a
where a.filter_condition = 0
and not exists (
select 1
from table_b b
where
a.column1 = b.column1
and a.column2 = b.column2
and a.column3 = b.column3
and a.column4 = b.column4
)
This will give you all records in table_a that do not have a corresponding record in table_b.
Using a LEFT JOIN between A and B and checking for a NULL row in B is probably easier:
SELECT *
FROM table_A A
LEFT JOIN table_B B ON A.column1 = B.column1
AND A.column2 = B.column2
AND A.column3 = B.column3
AND A.column4 = B.column4
WHERE B.column1 IS NULL
AND A.filter_condition = 0
You should be able to use tuples (aka row constructors) in PostgreSQL:
select *
from table_a
where filter_condition = 0
and (column1, column2, column3, column4) not in
(
select column1, column2, column3, column4
from table_b
);
If the columns can be null, then better use NOT EXISTS, as null=null results in "unknown" rather than in true or false.

how to save values from inner query result from a subquery in Oracle

How to save inner query result from a subquery execution
select b.column1, a.column1, a.column2, a.column3
from table1
where a.column4 = (select b.column1 from table2)
Can I get the combined result of 2 tables in subquery including inner query result?
Looks like a join to me.
select b.column1, a.column1, a.column2, a.column3
from table1 a join table2 b on a.column4 = b.column1

How does Inner join 3 or more tables works?

I saw some questions about the subject, but frankly i didn't quite understood.
What i want: I have five tables and i want to return a select with all intersections of the main table with the other 4. I'm currently doing 2 selects and then a UNION. It works great, but i guess i could improve the performance doing in a single select.
Here is an example of my code:
SELECT column1 FROM tableA A
INNER JOIN table B ON A.column1 = B.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE B.column2 IS NOT NULL
AND B.column3 = '7'
AND ( (D.column2 = 'x' OR D.column3 = 'y') OR (E.column2 = 'x' OR E.column3 = 'y') )
UNION
SELECT column1 FROM tableA A
INNER JOIN table C ON A.column1 = C.column1
LEFT JOIN table D ON A.column1 = D.column1
LEFT JOIN table E A.column1 = E.column1
WHERE C.column2 IS NOT NULL
AND C.column3 = '7'
AND ( (D.otherColumn2= 'x' OR D.otherColumn3 = 'y') OR (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y') )
About the tables.
Table A have the column1 shared with all the other tables:
(int) column1
Tables B and C have the same structure as follows:
(int) column1 | (int) column2 | (varchar) column3
And tables D and E also have the same structure:
(int) column1 | (varchar) otherColumn2 | (varchar) otherColumn3
As we can see, both selects are pretty much the same, with the exception of the table B and C.
I asked this question without the full code and #Kevin solved it. But with this extra information, and trying to follow his example, i changed the code to:
SELECT column1 FROM tableA A
LEFT JOIN table B ON (A.column1 = B.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table C ON (A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7')
LEFT JOIN table D ON A.column1 = D.column1
AND (D.otherColumn2 = 'x' OR D.otherColumn3 = 'y')
LEFT JOIN table E A.column1 = E.column1
AND (E.otherColumn2 = 'x' OR E.otherColumn3 = 'y')
WHERE
B.column1 is not null
or c.column1 is not null
or D.column1 is not null
or E.column1 is not null
But i getting a lot of extra results. I hope i'm making myself clear here, and if not, let me know and i will update this question.
You can always use exists:
select a.*
from tablea a
where exists (select 1 from tableb b where a.column1 = b.column1 and b.column3 = 7) or
exists (select 1 from tablec c where a.column1 = c.column1 and c.column3 = 7);
When you use join, you run the risk of getting duplicate rows -- and then you might do extra work to remove the duplicates. All unnecessary with exists.
And, for performance, you want indexes on tableb(column1, column3) and tablec(column1, column3).
This should get you what you want. However, I don't know that performance will be any better.
SELECT A.column1 FROM tableA A
LEFT JOIN tableB B ON A.column1 = B.column1
AND B.column2 IS NOT NULL
AND B.column3 = '7'
LEFT JOIN tableD d ON b.column1 = D.column1
LEFT JOIN tableE e ON B.column1 = E.column1
LEFT JOIN tableC C ON A.column1 = C.column1
AND C.column2 IS NOT NULL
AND C.column3 = '7'
LEFT JOIN tableD d2 ON c.column1 = d2.column1
LEFT JOIN tableE e2 ON c.column1 = e2.column1
WHERE (B.column1 is not null
and (d.othercolumn2 = 'x' or d.othercolumn3='y' or e.othercolumn2 = 'x' or e.othercolumn3='y')
)
or (c.column1 is not null
and (d2.othercolumn2 = 'x' or d2.othercolumn3='y' or e2.othercolumn2 = 'x' or e2.othercolumn3='y')
)
You can check it on sqlfiddle

build where clause to verify only once first clause is met

I have following sql select:
select ...
from table1 a, table2 b
where
a.column = 'ABC' and
a.column2 = b.column2
I would like to only check if a.column2 = b.column2 when a.column = 'ABC'.
How do I do that?
Thanks
I'm not sure from your question tag if you're trying to figure out how to do this with a JOIN specifically (as opposed to how you did it with the WHERE clause), but anyway -- a couple of ways:
1) --with WHERE clause
select ...
from
table1 a
INNER JOIN table2 b
ON a.column2 = b.column2
where
a.column = 'ABC'
2) --WITHOUT WHERE CLAUSE
select ...
from
table1 a
INNER JOIN table2 b
ON a.column2 = b.column2
AND a.column = 'ABC'
Try this. It will check column2 only when column is 'ABC':
select ...
from table1 a, table2 b
where
(a.column = 'ABC' and
a.column2 = b.column2) or a.column <> 'ABC'

Using a Oracle subselect to replace a CASE statement

Hy guys,
can anybody please help me with a subquery in Oracle database 10g? I need to extract the values for a column in the first table as value of another column in the second table.
I currently use this statement:
SELECT
CASE WHEN A.column1 = 'A' THEN 'aaa'
WHEN A.column1 = 'B' THEN 'bbb'
.......
WHEN A.column1 = 'X' THEN 'xxx'
ELSE 'bad' END AS COLUMN1, A.*
FROM TRANSACTION_TABLE A, CATEGORY_TABLE B
WHERE A.column1 IS NOT NULL
AND A.column1 <> ' '
This is not an elegant approach, so I'm trying to use a subselect from CATEGORY_TABLE B like the following:
SELECT A.column1, A.*
FROM TRANSACTION_TABLE A, CATEGORY_TABLE B
WHERE A.column1 IS NOT NULL
AND A.column1 = B.column_b_1
AND A.column1 <> ' '
AND A.column1 IN (SELECT B.column_b_1_descr FROM CATEGORY_TABLE B
WHERE B.FIELDNAME = 'column1' AND A.column1 = B.column_b_1)
So, I cannot get any results by using the subquery and don't want to continue using the CASE against many conditions, just want to replace the A.column1 values with the descriptive values from B.column_b_1_descr , as they're easier to read.
I would appreciate any feedback.
Thanks
Unless I'm misunderstanding your question...
CATEGORY_TABLE:
name | value
A aaa
B bbb
C ccc
...
SELECT B.value AS COLUMN1, A.\*
FROM TRANSACTION\_TABLE A, CATEGORY\_TABLE B
WHERE A.column1 = B.name
or
SELECT t2.value as COLUMN1, t1.\*
FROM TRANSACTION\_TABLE t1
INNER JOIN CATEGORY\_TABLE t2 ON t1.column1 = t2.name;
The where clause isn't needed, since an inner join automatically excludes rows with null values or no matches.