Conditional join in SQL depending on a column value - sql

I'm trying to do a join on a SAS table using PROC-SQL. Depending on the value of one variable in table A I need to join using a column, otherwise I need to use another column.
proc sql;
create table test
as select
A.*,
A.PPNG_RVNE * B.perc_ress as variable1,
A.P_RVNE * B.perc_ress as variable2
from tableA as A
left join tableB as B
on case when A.cod_cia = 1 then A.cod_cia=B.cod_cia and A.cod_agrup_produto=B.cod_agrup_produto
else A.cod_cia=B.cod_cia and A.projeto=B.projeto;
I need to join just to create variable1 and variable2. I don't want to select any variable from table B.
My cod doesn't run. SAS gives me an error message saying that it is expecting an `end.
Does anyone know how to conditional join depending on columns?

Don't use case. Just express the logic booleanly"
proc sql;
create table test as
select A.*, A.PPNG_RVNE * B.perc_ress as variable1, A.P_RVNE * B.perc_ress as variable2
from tableA A left join
tableB B
on A.cod_cia = B.cod_cia and
(A.cod_cia = 1 and A.cod_agrup_produto = B.cod_agrup_produto) or
(A.cod_cia <> 1 and A.projeto = B.projeto);
Note: This uses <> 1. If cod_cia could be NULL you need to take that into account. Also note that this factors out the first condition.

Not a PROC-SQL user so apologies if this is wrong, but based on this question a case statement needs the format:
CASE
WHEN ... THEN ...
WHEN ... THEN ...
ELSE ...
END
So have you tried:
proc sql;
create table test
as select
A.*,
A.PPNG_RVNE * B.perc_ress as variable1,
A.P_RVNE * B.perc_ress as variable2
from tableA as A
left join tableB as B
on case when A.cod_cia = 1 then A.cod_cia=B.cod_cia and A.cod_agrup_produto=B.cod_agrup_produto
else A.cod_cia=B.cod_cia and A.projeto=B.projeto
end;

I would use two joins and a coalesce statement:
proc sql;
create table test
as select
A.*,
A.PPNG_RVNE * coalesce(B1.perc_ress,B2.perc_ress) as variable1,
A.P_RVNE * coalesce(B1.perc_ress,B2.perc_ress) as variable2
from tableA as A
left join tableB as B1
on A.cod_cia = 1 and A.cod_cia=B1.cod_cia and A.cod_agrup_produto=B1.cod_agrup_produto
left join tableB as B2
on A.cod_cia=B2.cod_cia and A.projeto=B2.projeto;
you could add A.cod_cia ne 1 in the second join, but it's not necessary unless.

Related

using define to store the result of a select statement

Good evening, i want to ask about the feasibility of something so i have a select statement inside this select a lot of similare subqueries
i want to use a sub-query only once and store it's result I have tried something like that but I don't know what to do
any help would be appreciated
define A = Select somthing from TableA
Select case
when A <0
then 1
else 2
End as selectedcolumn from TableB
But i think that define is used only with static values
You can do this with a CTE, e.g.
WITH A AS
SELECT COUNT(*) c FROM TableA A
WHERE A.ColumnA = B.ColumnB
AND A.ColumnA2 = 0
Select A.c As test
from TableA ta
inner join TableB tb
on ta.columnA=tb.columnB
cross join A
This will make A.c available in your query. You can also then do (select c from A) anywhere in your query to get the value.
Alternately, if you're running a script in SQL*Plus, you can define a column variable using new_value:
COLUMN my_count NEW_VALUE my_constant
SELECT COUNT(*) my_count FROM TableA A
WHERE A.ColumnA = B.ColumnB
AND A.ColumnA2 = 0;
Then you can refer to it later on in your script using the substitution string &&my_constant:
Select case
when &&my_constant <0
then 1
else 2
End as selectedcolumn from TableB

SQL Select where condition : value 1 <> value 2

Need your help to know if possible to select values from a table with the below condition :
Table content : matching between 2 objects
(Id_obj_A; name_obj_A; country_obj_A; Id_obj_B; name_obj_B; country_obj_B)
Select *
from table
Where (only if country_obj_A <> country_obj_B)
Many thanks for your help
Yes. There are a few ways, one is to use NOT EXISTS like this:
select
*
from tableA
where NOT EXISTS (
select NULL
from tableB
where tableB.country_obj_B = tableA.country_obj_A
)
or, using NOT IN
select
*
from tableA
where country_obj_A NOT IN (
select country_obj_B
from tableB
)
or, using a LEFT JOIN then exclude the joined rows:
select
*
from tableA
left join tableB on tableA.country_obj_A = tableB.country_obj_B
where tableB.country_obj_B IS NULL

find the code in table A which does not have in table B for particular gr_code

I have two table in my same DB
create table a(gr_code nvarchar, code int)
insert into a values('1',100),('0',200),('1',200),('0',100)
create table b(gr_code nvarchar, code int)
insert into b values('1',100),('0',200)
find the code in table A which does not have in table B for particular gr_code
expected result:
gr_code code
1 200
0 100
It's quite simple using the clause exists
select *
from a
where not exists (select *
from b
where b.gr_code = a.gr_code and
b.code = a.code)
This returns the result on your sample.
Use LEFT JOIN
select a.*
from a
left join b on a.gr_code = b.gr_code and a.code = b.code
where b.gr_code is null
You can use LEFT JOIN like this:
SELECT a.*
FROM a
LEFT JOIN b on a.gr_code = b.gr_code
WHERE b.gr_code IS NULL
You can use EXCEPT like so:
select *
from a
except
select *
from b

PROC SQL - Case when with multiple tables

I need to create a dataset (TABLE3) in order to check if some variables from other two tables are equals. If so, the code must return 0, otherwise 1. But, as I'm a new user of SAS and SQL I'm struggling to figure out how to do that.
I'm trying something like that but it's not working.
PROC SQL;
CREATE TABLE TABLE3 AS
SELECT A.*, B.*
CASE WHEN B.VARIABLE1 = A.VARIABLE2 THEN 0 ELSE 1 END AS VARIABLE_1_2,
CASE WHEN B.VARIABLE3 = A.VARIABLE4 THEN 0 ELSE 1 END AS VARIABLE_3_4
FROM TABLE1 AS A
LEFT JOIN TABLE2 AS B;
P.S.: Variables 1, 2, 3 and 4 are all character variables.
In addition to the tables relation you must add after the join, You miss a coma "," just before the first case.
For a JOIN condition to work, there must a ON clause
PROC SQL;
CREATE TABLE TABLE3 AS
SELECT A.*, B.*,
CASE WHEN B.VARIABLE1 = A.VARIABLE2 THEN 0 ELSE 1 END AS VARIABLE_1_2,
CASE WHEN B.VARIABLE3 = A.VARIABLE4 THEN 0 ELSE 1 END AS VARIABLE_3_4
FROM TABLE1 AS A LEFT JOIN TABLE2 AS B
**ON TABLE1.SOME_COLUMN_NAME = TABLE2.SOME_COLUMN_NAME**
;

calculate value based on 2 fields in SQL database

I can do this with linq easy but i got a situation where i have to create a stored procedure to return true or false based on 2 fields(minrange,maxrange) in table B. So, the goal is given an id from table A, i select the range value from table A and compare this value to the 2 ranges in table B. If the value is within range(minrange,maxrange) return true. Thanks.
I'm assuming you have a field that allows you to join records from Table A to Table B. I'll call it "CategoryID". Try this:
SELECT
CASE WHEN TableA.Value BETWEEN TableB.MinValue AND TableB.MaxValue
THEN 1 ELSE 0 END
FROM TableA
INNER JOIN TableB ON TableA.CategoryID = TableB.CategoryID
WHERE TableA.ID = "TheID"
Good luck!
-Michael
Without knowing specifics (as to foreign keys), this syntax should work.
SELECT
CAST((CASE
WHEN tableAValue < tableB.maxRange and tableAValue > tableB.minRange
THEN 1
ELSE
0
END) AS BIT)
FROM TableA
INNER JOIN TableB
ON TableA.ID = TableB.TableAID
WHERE TableA.ID = #yourID