Is there a way to join 2 tables together on one and only one of the possible conditions? Joining on condition "a" or "b" could duplicate rows, but I'm looking to only join once. I came up with a potential solution, but I'm wondering if there is a more slick way to do it.
For example:
SELECT *
FROM TableA a
LEFT JOIN TableB b
ON a.col1 = b.col1
OR (a.col1 != b.col1 AND a.col2 = b.col2)
This would join the tables on col1 OR col2 BUT NOT BOTH. Is there a cleaner way of doing this?
Not more efficient but I think more clear
SELECT *
FROM TableA a
LEFT JOIN TableB b
ON (a.col1 = b.col1 or a.col2 = b.col2)
AND NOT (a.col1 = b.col1 and a.col2 = b.col2)
Your method works. If you only want one (or a handful) of columns from b, I would suggest:
SELECT a.*, COALESCE(b.col3, b2.col3)
FROM TableA a LEFT JOIN
TableB b
ON a.col1 = b.col1 LEFT JOIN
TableB b2
ON a.col1 <> b2.col1 AND a.col2 = b2.col2;
Removing the OR from the JOIN conditions allows the optimizer to generate a better execution plan.
SELECT A.COL1, A.COL2, A.COL3, A.COL4
FROM TABLE A, TABLE B
WHERE B.COL1 = A.COL1
AND B.COL2 = A.COL2
AND B.COL3 - A.COL3
AND B.COL4 = A.COL4
Now I want to tune the SQL query, that whenever any of the Columns in Table B has field value 'ALL' the where clause will not come into picture.
i.e. When it has a distinct value it will match with both the tables, when the field value is 'ALL' then to exclude from the where clause.
Alternatively,
I Need B.COL1= A.COL1 (When B.COL1 <> 'ALL')
Else NO WHERE clause with B.Col1 = A.Col1 (When B.COL1 = 'ALL')
Use OR wisely:
SELECT A.COL1, A.COL2, A.COL3, A.COL4
FROM TABLE A, TABLE B
WHERE (B.COL1 = A.COL1 OR B.COL1='ALL')
AND (B.COL2 = A.COL2 OR B.COL2='ALL')
...
I would also suggest learning JOIN syntax.
Hi, You can use case statement to have a condition in where clause,
SELECT A.COL1, A.COL2, A.COL3, A.COL4
FROM TABLE A, TABLE B
WHERE B.COL1 =
CASE
WHEN B.COL1 <> 'ALL' THEN A.COL1
ELSE NULL
END
AND B.COL2 = A.COL2
AND B.COL3 - A.COL3
AND B.COL4 = A.COL4
You can achieve this with just IN:
SELECT A.COL1, A.COL2, A.COL3, A.COL4
FROM TABLE A, TABLE B
WHERE B.COL1 IN (A.COL1, 'ALL')
AND B.COL2 IN (A.COL2, 'ALL')
AND B.COL3 IN (A.COL3, 'ALL')
AND B.COL4 IN (A.COL4, 'ALL')
What is actually going on may be more clear with a more verbose version using AND/OR, but the logic is exactly the same
SELECT A.COL1, A.COL2, A.COL3, A.COL4
FROM TABLE A, TABLE B
WHERE (B.COL1 = A.COL1 OR B.COL1 = 'ALL')
AND (B.COL2 = A.COL2 OR B.COL2 = 'ALL')
AND (B.COL3 = A.COL3 OR B.COL3 = 'ALL')
AND (B.COL4 = A.COL4 OR B.COL4 = 'ALL')
Simple solution:
SELECT DISTINCT A.COL1, A.COL2, A.COL3, A.COL4
FROM TABLE A
INNER JOIN TABLE B ON
(B.COL1 = A.COL1 AND B.COL2 = A.COL2 AND B.COL3 = A.COL3 AND B.COL4 = A.COL4)
OR
('ALL' IN (B.COL1, B.COL2, B.COL3, B.COL4))
but, if you work with large tables that complex filtering could slow down very much the execution, so I suggest to use a different syntax for complex JOINs
SELECT DISTINCT *
FROM (
SELECT A.COL1, A.COL2, A.COL3, A.COL4
FROM A
INNER JOIN B
ON (B.COL1 = A.COL1 AND B.COL2 = A.COL2 AND B.COL3 = A.COL3 AND B.COL4 = A.COL4)
) J1
UNION -- ALL ?
SELECT DISTINCT *
FROM (
SELECT A.COL1, A.COL2, A.COL3, A.COL4
FROM A
INNER JOIN B ON ('ALL' IN (B.COL1, B.COL2, B.COL3, B.COL4))
) J2
This one should be much faster than previous one.
Also, I wonder about row duplicates.. with that syntax each row of table A will be added to result as many times as many rows in table B contains 'ALL'
I have added the DISTINCT clause to the SELECT to avoid duplicates (same problem affects UNION operator), so if you need duplicates, remove DISTINCT and use UNION ALL instead of UNION
I have two tables, say A and B. I wish to compare three or more columns in both tables and to return any rows in table B that don't match all of the compared columns.
I've looked at doing a left join function from recommendations, but can't quite figure it out.
Please help!
You can use left join or not exists for this. Here is one method:
select b.*
from tableb as b
where not exists (select 1
from tablea as a
where a.col1 = b.col1 and a.col2 = b.col2 and a.col3 = b.col3
);
how about something like this
Select b.col1,b.col2,b.col3 from
tableb b left outer join tablea a
on ( b.col1 != a.co11 and b.col2 != a.co12 and b.col3 != a.co13 )
My delete statement returns a 933 error in Oracle, I'm not sure what is wrong-
DELETE b
from temp a
JOIN
fact_tab b
on a.col1 = b.col1
and a.col2 = b.col2
and a.col3 = b.col3;
Both tables dont have a primary key. select statement on the same thing works-
select *
from temp a
JOIN
fact_tab b
on a.col1 = b.col1
and a.col2 = b.col2
and a.col3 = b.col3;
try this
DELETE FROM
fact_tab
WHERE
EXISTS
(
SELECT
1
FROM
temp
WHERE
temp.col1 = fact_tab.col1 AND
temp.col2 = fact_tab.col2 AND
temp.col2 = fact_tab.col2
)
Oracle doesn't allow JOIN in a DELETE statement directly like that.
You could do the delete in the following way:
DELETE
FROM fact_tab
WHERE ROWID IN
(SELECT b.rowid
FROM temp a
JOIN fact_tab b
ON a.col1 = b.col1
AND A.col2 = b.col2
AND A.col3 = b.col3
);
You could also use WHERE EXISTS clause.
I have a sql query as below:
SELECT
A.COL1, A.COL2
FROM
SOMESCHEMA.TABLE1 A
WHERE
A.COL3 NOT IN (SELECT A1.COL3 FROM SOMESCHEMA.TABLE2 B, SOMESCHEMA.TABLE1 A1 WHERE A.COL4 = B.COL4 AND B.DATE >= '2014-01-17')
The result of above query is two columns COL1 and COL2.
Now I want the DATE column of the second table into my result.
That is, the result should be COL1, COL2 and DATE.
How to achieve this?
Thanks for reading!
This is exactly the situation you want to use a join:
SELECT
A.COL1, A.COL2, B.DATE
FROM
SOMESCHEMA.TABLE1 A INNER JOIN SOMESCHEMA.TABLE2 B ON A.COL3 = B.COL3
WHERE B.DATE >= '2014-01-17'
You can find more info on using JOINS in DB2 here: http://www-01.ibm.com/support/knowledgecenter/?lang=en#!/SSEPEK_10.0.0/com.ibm.db2z10.doc.intro/src/tpc/db2z_innerjoin.dita
Your question as stated makes no sense - you're asking for matched data where the data does not match. Sample data from each table and a sample output would really help here.
Here is my best guess as to what you're trying to do:
Return data from Table2 where a match on COL4 exists that is greater than January 17th and has with a different COL3
SELECT
A.COL1, A.COL2, B.DATE
FROM
SOMESCHEMA.TABLE1 A
INNER JOIN
SOMESCHEMA.TABLE2 B ON
A.COL4 = B.COL4 AND
B.DATE >= '2014-01-17' AND
A.COL3 <> B.COL3