SQL how to check is a value in a col is NOT in another table - sql

Maybe I need another coffee because this seems so simple yet I cannot get my head around it.
Let's say I have a tableA with a col1 where employee IDs are stored.... ALL employee IDs. And the 2nd table, tableB has col2 which lists all employeeID who have a negative evaluation.
I need a query which returns all ID's from col1 from table1 and a newcol which show a '1' for those ID's which do NOT exist in col2 of TableB.
I am doing this in dashDB

One option uses a LEFT JOIN between the two tables:
SELECT a.col1,
CASE WHEN b.col2 IS NULL THEN 1 ELSE 0 END AS new_col
FROM tableA a
LEFT JOIN tableB b
ON a.col1 = b.col2

Alternatively you can achieve your requirement with LEFT JOIN along with IFNULL function as below.
SELECT a.col1,
IFNULL(b.col2, 1) NewCol
FROM tableA a
LEFT JOIN tableB b
ON a.col1 = b.col2

Related

filtering for column pairs in SQL

consider two tables that have the following columns
A
1,X
2,Y
3,Z
B
1,X
1,Y
1,Z
2,X
2,Y
2,Z
3,X
3,Y
3,Z
is it possible select rows in B that have column pairs as in A without joining or a third column?
something like
select * from B where distinct columns in (select distinct columns from A)
You could use exists logic:
SELECT col1, col2
FROM TableB b
WHERE EXISTS (SELECT 1 FROM TableA a WHERE a.col1 = b.col1 AND a.col2 = b.col2);

Why 'where' statement seems to filter expected rows in SAS proc SQL?

I full joined 2 tables first and then full joined a 3rd table, now I got 1000 more rows in the result. But when I added a where statement following the join process I can only get 200 more rows and it seems that some expected rows were filtered. I don't know what I've done wrong.
proc sql;
create table ECG.RECON as
select a.SUBJID as SUBJID_004 ,
a.VISIT as VISIT_004,
input(a.EGDAT, yymmdd10.) as EGDAT_004 ,
...
b.SUBJID as SUBJID_001 ,
...
c.DSDECOD
from
SOURCE.A a full join SOURCE.B b on
(a.SUBJID = b.SUBJID and a.VISIT = b.VISIT )
full join SOURCE.C as c on b.SUBJID = c.SUBJID
where c.EPOCH = "SCR" and c.DSDECOD ne "FAILURE" and a.TEST = "Inter";
quit;
Your where clause is causing empty rows to be filtered. Consider a simplified schema:
TableA
Col1 Col2
----------------
1 A
2 B
TableB
Col1 Col2
----------------
1 X
3 Y
And a simple full join with no filter:
SELECT *
FROM TableA AS A
FULL JOIN TableB AS B
ON A.Col1 = B.Col1
Which will return
A.Col1 A.Col2 B.Col1 B.Col2
---------------------------------------
1 A 1 X
2 B NULL NULL
NULL NULL 3 Y
Now, if you apply a filter to anything from A, e.g. WHERE A.Col1 = 1, you'll get rid of the 2nd Row (probably as intended) since 2 <> 1, but you'll also remove the 3rd row, since A.Col is NULL, and NULL <> 1. As you have removed all rows with no matching record in TableA you have effectively turned your full join into a left join. If you then apply a further predicate on TableB, your left join becomes an inner join.
With Full joins, I find the easiest solution is to apply your filters before the join by using subqueries, e.g.:
SELECT *
FROM (SELECT * FROM TableA WHERE Col1 = 1) AS A
FULL JOIN TableB AS B
ON A.Col1 = B.Col1;
Which removes the 2nd row, but still retains the 3rd row from the previous results:
A.Col1 A.Col2 B.Col1 B.Col2
---------------------------------------
1 A 1 X
NULL NULL 3 Y
You can also use OR, but the more predicates you have the more convoluted this can get, e.g.
SELECT *
FROM TableA AS A
FULL JOIN TableB AS B
ON A.Col1 = B.Col1
WHERE (Col1 = 1 OR A.Col1 IS NULL);

PostgreSQL comparing null values in case statement

when I wrote a case statement to compare values in tables, it came unstuck with variables that are null. It thinks they are different (note: col1 is a character field).
select a.id,
a.col1 as a_col1,
b.col1 as b.col1,
case when a.col1=b.col1 then 0 else 1 end as chk_col1
from tablea a,
tableb b
where a.id=b.id;
... chk_col1 is always 0 when both col1's are null. I've tried
coalesce(a.col1,'null') as coalesce(b.col1,'null')
but this didn't work either. It still returned 1 for chk_col1.
Postgres supports the null-safe comparison operator is not distinct from. So, try this:
select a.id,
a.col1 as a_col1,
b.col1 as b.col1,
(case when a.col1 is not distinct from b.col1 then 0 else 1 end) as chk_col1
from tablea a join
tableb b
on a.id = b.id;
Personally, I would leave the value as a boolean:
select a.id, a.col1 as a_col1, b.col1 as b.col1,
(a.col1 is distinct from b.col1) as chk_col1
from tablea a join
tableb b
on a.id = b.id;
Also note that I used proper, explicit, standard, readable JOIN syntax.
SOLUTION! :
The variable referenced in the colaesce function must be the calculated one, i.e.
coalesce(a_col1,'null') as coalesce(b_col1,'null')
Another thing I discovered. Let's say col2 is numeric. The above doesn't work, you'd need to use a 0. Or ... more cunningly, you can use '0', i.e.
coalesce(a_col2,'0') as coalesce(b_col2,'0')
This is handy to know if you want to generate some code to compare tables by referencing pg_tables or svv_columns. In this code I had 2 tables that I'd created by reading svv_columns metadata table, and I wanted to created a case statement for each variable, so I'd have the two variables from each table side by side plus a check variable which I'd use for summarising later:
select ' coalesce(a.'||a.column_name||',''0'') as a_'||a.column_name||', coalesce(b.'||b.column_name||',''0'') as b_'||b.column_name||', case when a_'||a.column_name||'=b_'||b.column_name||' then 0 else 1 end as chk_'||a.column_name||','
from tbl_a_vars a,
tbl_b_vars b
where a.column_name=b.column_name;

SQL: How to know if a LEFT JOIN returned a row?

Simple problem. I have a simple SQL as thus...
SELECT a.Col1, a.Col2, XXX
FROM table1 AS a
LEFT JOIN table2 as b
ON b.Key1 = a.Key1
What can I put in the 'XXX' above to say something like "does table B exists?".
ie: EXISTS(b) AS YesTable2
I am hoping there is a simpler solution than just using CASE...END statements.
Thanks
You could use ISNULL(b.Key1, 'XXX') Or COALESCE for checking against multiple values for the first non null value.
Pick any column from b that is not allowed to be NULL. If there is a NULL there, the record does not exist. If there is a value there, the record does exist. If every column in b is allowed to be NULL (rare: you should always have something that's not nullable in the primary key) you'll have to build an expression that mimics the JOIN conditions.
I am hoping there is a simpler solution than just using CASE...END statements.
Your guess is spot-on: you can use CASE...END to compare b.Key1 to NULL, like this:
SELECT
a.Col1
, a.Col2
, CASE WHEN b.Key1 IS NOT NULL THEN 1 ELSE 0 END as YesTable2
FROM table1 AS a
LEFT JOIN table2 as b
ON b.Key1 = a.Key1
If you just want to know if a record exists, I would suggest using exists in the select clause:
SELECT a.Col1, a.Col2,
(CASE WHEN EXISTS (SELECT 1 FROM table2 b ON b.Key1 = a.Key1)
THEN 1 ELSE 0
END) as ExistsInTable2
FROM table1 a;
This version will guarantee that you do not get duplicated rows if there are multiple matches in the two tables.

How to choose a proper filter for an sql join

If I have table A and table B, each with one column:
A:
col1
1
2
3
1
B:
col1
1
1
4
and I want all rows from A and the matching rows from B, only when the column has non null value in both tables, which one should I use?
select * from A left join B on A.col1 = B.col1 and A.col1 is not null AND B.col1 is not null;
select * from A left join B on A.col1 = B.col1 where A.col1 is not null OR B.col1 is not null;
select * from A left join B on A.col1 = B.col1 and (A.col1 is not null OR B.col1 is not null;)
My guess is that the first and the third are the same and will provide the desired output.
If you want to skip null values and you want to link both tables only on existing values you should use an INNER JOIN, the null check is redundant:
SELECT A.*
FROM A INNER JOIN B ON A.col1 = B.col1
NULL will never match any other value (not even NULL itself), unless the join condition explicitly uses the IS NULL or IS NOT NULL predicates.
In a comment you said you are checking for more than nulls in this case I would probaly take thederived table or CTE approach. Dervied table shown below as you did not specify which database backend, so I don't know if you can use CTEs.
select
from
(select from tablea where test is not null or test <>'' or test<>'N/A') a
JOin
(select from tableb where test is not null or test <>'' or test<>'N/A')b
ON a.col1 = b.col1
You just need
select * from A left join B on A.col1 = B.col1
NULL will never match anything (when not compared with IS NULLand the like), therefore NULL in A won't match anything in B.
Since you want all the rows from A, below query should work:
select * from A left outer join B on A.col1 = B.col1 where A.col1 is not null and A.col1<>'N/A' and A.col1<>''
http://sqlfiddle.com/#!2/98501/14