Ambiguious column refernce in Union All - sas

I am receiving an error message with my union all indicating that member_key is ambiguous. Adding an alias does not seem to resolve this. Any suggestions?
proc sql;
Select distinct member_key
into: member_ky_list separated by ","
From(
select
member_key
from work.Member_Admit_icd
UNION ALL
Select
member_key
from work.Member_ICD
UNION ALL
Select
member_key
from work.member_cpt);
Quit;

It seems to be a misleading error message.
I was able to replicate the error only when at least for one of the table the member_key does not exist in the source tables.
data member_admit_icd member_icd member_cpt(drop=member_key);
set sashelp.cars;
member_key=1;
run;
proc sql;
select distinct member_key into: member_ky_list separated by ","
from (
select member_key
from work.Member_Admit_icd
UNION ALL
select member_key
from
work.Member_ICD
UNION ALL
select member_key
from work.member_cpt
);
quit;
ERROR: Ambiguous reference, column member_key is in more than one table.
Please check that the member_key variable is present in every source table.

Related

How to insert records from other tables to a table with more columns in sas

I have two sas tables, A and B, A has two columns (i.e., columna columnb) and table B has four columns (i.e., columna columnb columnc columnd ), I wish to insert records from table A to table B, I tried the following, but it shows me errors:
PROC SQL;
insert into B
select *, columnc='a', columnd='b' from A;
QUIT;
Assuming you just want to leave the extra columns empty then don't include them in the insert. It is much easier to just use SAS code instead of SQL code.
proc append base=b data=a force nowarn;
run;
For the SQL Insert statement you need to specify which columns in the target table you are writing into, otherwise it assumes you will specify values for all of them.
insert into B (columna,columnb)
select columna,columnb
from A
;
If instead you want to fill the extra columns with constants then include the constants in the SELECT list.
insert into B (columna,columnb,columnc,columnd)
select columna,columnb,'a','b'
from A
;
If you are positive that you are providing the values in the right order then you can leave the column names off of the target table specification.
insert into B
select *,'a','b'
from A
;
You can't specify the variable name that way; in fact, you can't specify the variable at all using insert into. See this example:
proc sql;
create table class like sashelp.class;
alter table class
add rownum numeric;
alter table class
add othcol numeric;
insert into class
select *, 1 as othcol, monotonic() as rownum from sashelp.class;
quit;
Here I use as to specify the column name, but notice that it doesn't actually work: it puts 1 in the rownum column, and the monotonic() value in othcol, since they're in that order on the table.

SAS: Variable list contains names with '-' symbol, resulting in error during keep= statement

I have SAS datasets with multiple variables like H9999-999-999-999. However, I need to drop the unnecessary columns and am using a variable list(ParamList) to do that:
proc sql;
select _NAME_ into :ParamList separated by ' '
from uniquePlanList;
quit;
%put ParamList = &ParamList.;
proc sql;
create table test as
select * from out.seq_summ(keep=BPT_Cat &ParamList.);
run;
Because my variables contain '-' symbols I receive the following errors:
ERROR 214-322: Variable name - is not valid.
ERROR 214-322: Variable name 000 is not valid.
ERROR 80-322: Expecting a variable name.
ERROR: Invalid value for the KEEP option.
ERROR: Invalid option name -000.
ERROR: Some options for file OUT.SEQ_SUMM were not processed because of errors or warnings noted above.
I know if I were to list out the variables like this:
(keep=BPT_Cat 'H9999-999-999-999'n 'H9999-999-999-998'n)
Then the code would work. But I have some datasets with hundreds of variables. Is there a better way to drop the unnecessary columns than using a variable list? Or is there some clever way to read in the variable list as a string?
I tried using this:
(keep=BPT_Cat %str(&ParamList.)) but that gave me the same errors as above.
Use the NLITERAL() function to generate names in a form that you can use in code.
proc sql noprint;
select nliteral(_NAME_)
into :ParamList separated by ' '
from uniquePlanList
;
quit;
how about:
proc sql;
select quote(_NAME_)||"n" into :ParamList separated by ' '
from uniquePlanList;
quit;
%put ParamList = &ParamList.;
proc sql;
create table test as
select * from out.seq_summ(keep=BPT_Cat &ParamList.);
run;
Don't have SAS with me at the moment can't really test it.

Joining two sets in SAS SQL with table/correlation error

I am trying to join two datasets. The first dataset1 has two columns item and price. The second dataset2 has three columns - item, customerid, and qty. I need to only include the unique rows from dataset1 that are not in dataset2. While trying to implement this code, I get the error:
Error: Unresolved reference to table/correlation name i.
I am unsure how to fix this error, thanks.
PROC SQL;
create table a as
select *
from dataset1 as i
except corr
select *
from dataset2 as p
where i.item = p.item;
describe table a;
QUIT;
EXCEPT is used to select records in the first set that do not exist in the second set. So if what you want is, to quote you, select records from dataset1 that do not appear in dataset2, you don't need the where clause:
PROC SQL;
create table a as
select *
from dataset1 as i
except corr
select *
from dataset2 as p
;
QUIT;
If however, like that where clause would suggest, you actually want to select records from dataset1 where the value of item is not found in dataset2, you could do this
proc sql;
select *
from dataset1 i
where not exists (select *
from dataset2 p
where i.item=p.item
)
;
quit;
EDIT: following your latest comment, and if you reaaaally need your query to feature an except, this should get you your result
proc sql;
create table a as
select t1.*
from dataset1 t1
inner join (select *
from dataset1 as i
except corr
select *
from dataset2 as p
) t2
on t1.item=t2.item
;
quit;
Even though this will do the same as the query above (with not exists) or, now that I think of it (stupid me), as this:
proc sql;
create table a as
select *
from dataset1
where item not in (select distinct item from dataset2)
;
quit;

How to count distinct of the concatenation/cross of two variables in SAS Proc Sql?

I know in teradata or other sql platforms you can find the count distinct of a combination of variables by doing:
select count(distinct x1||x2)
from db.table
And this will give all the unique combinations of x1,x2 pairs.
This syntax, however, does not work in proc sql.
Is there anyway to perform such a count in proc sql?
Thanks.
That syntax works perfectly fine in PROC SQL.
proc sql;
select count(distinct name||sex)
from sashelp.class;
quit;
If the fields are numeric, you must put them to character (using put) or use cat or one of its siblings, which happily take either numeric or character.
proc sql;
select count(distinct cats(age,sex))
from sashelp.class;
quit;
This maybe redundant, but when you mentioned "combination", it instantly triggered 'permutation' in my mind. So here is one solution to differentiate these two:
DATA TEST;
INPUT (X1 X2) (:$8.);
CARDS;
A B
B A
C D
C D
;
PROC SQL;
SELECT COUNT(*) AS TOTAL, COUNT(DISTINCT CATS(X1,X2)) AS PERMUTATION,
COUNT(DISTINCT CATS(IFC(X1<=X2,X1,X2),IFC(X1>X2,X1,X2))) AS COMBINATION
FROM TEST;
QUIT;

Proc sql VALIDATE with CREATE TABLE

I am working in SAS EG and I have code like this:
proc sql;
CREATE TABLE new as
SELECT f1,f2
FROM work.orig
WHERE f1<>'x'
;
This works.
However, when I add a VALIDATE option, like below, I get an error:
ERROR 22-322: Syntax error, expecting one of the following: (, SELECT.
ERROR 202-322: The option or parameter is not recognized and will be ignored.
proc sql;
CREATE TABLE new as
VALIDATE
SELECT f1,f2
FROM work.orig
WHERE f1<>'x'
;
How do I use the validate option in proc sql?
My understanding is that you cannot use the VALIDATE with the CREATE statement.
Validate the underlying SELECT
proc sql;
VALIDATE
SELECT f1,f2
FROM work.orig
WHERE f1<>'x'
;
quit;
If that is successful, then your CREATE statement will work.