is there a solution for putting the select statement in brackets or something like this?
I need to perform this:
select t1.plz, t1.help, t1.me AS...
The Problem is, that my columns getting from a variable and my code perform this
select t1.plz, help, me
It works to the point i join it with an other table and the key gets mixed up. This works - t2.key, car,...
but
t2.car,key not, because i need to rename key as key2 and without the t2.key in front it doenst work...long story.
I need to get that t1./t2. in front of every column.
Is there a solution for this problem?
My Code(SAS)
create table work.test as
select t1.&string1 t2.&string2
I canĀ“t put the t1. in front of every string, because i perform a loop, so this would end in a t1.plz, t1.t1.help, t1.t1.t1,me.
Use the TRANWRD() function to replace all the ", " with ", t1." then use SYMPUTX() to create the macro variables.
The Code below will fix this for you by creating the macros with the correct prefix:
data _null_;
%let str1= "plz, help, me";
%let str2= "plz, help, me";
t1= cats('t1.',tranwrd(&str1,", ",", t1."));
t2= cats('t2.',tranwrd(&str2,", ",", t2."));
call symputx('string1',t1,'L');
call symputx('string2',t2,'L');
put _all_;
run;
Output: The two macros &string1 and &string2 will have the values below.
t1.plz, t1.help, t1.me
t2.plz, t2.help, t2.me
Related
I am wondering what approach should have been selected to perform action from title. I am using ODBC connection and what I get from first sql query are like 40-50 rows in one column. What I want is to put this output as a values in to search for.
How should i treat this? Like a array or separated variables? I still do not know R well so just need to know where to search for.
Regards
------more explanation below----
I have list of 40-50 numbers of 10 digits each, organized in a column.
I am trying to do this:
list <- c(my_input)
sql_in <- paste0(list, collapse="")
and characters are organized like this after this operations:
'c(1234567890, , 1234567890, 1234567890)'
and almost all looks fine and fit into my query besides additional c character at the beginning and missing apostrophes.I try to use gsub function but did not work in way I want.
You may likely do this in one SQL call using a subquery. Notice in the call below that the result of
SELECT n_gear
FROM Gear
WHERE n_gear IN (3,4)
Is passed to the WHERE clause of the primary query. This is perfectly valid and will allow your query to execute entirely in SQL without having to do any intermediate steps in R.
(I use sqldf for simplicity of illustration, but this should work through just about any ODBC connection)
library(sqldf)
Gear <- data.frame(n_gear = 1:5)
sqldf(
"SELECT mpg, qsec, gear, wt
FROM mtcars
WHERE gear IN (SELECT n_gear
FROM Gear
WHERE n_gear IN (3,4))"
)
Try something like this:
list<-c("try","this") #The output from your first query
sql_in<-paste0(list, collapse="','")
The Output
paste("select * from table where table.var in ",paste("('",sql_in,"')",sep=''))
[1] "select * from table where table.var in ('try','this')"
If yuo have space as first or last element of the string you can use this code:
`list<-c(" first element is a space","try","this","last element is a space ")` #The output from your first query
Find space at first or last character
first_space<-substr(list, start = 1, stop = 1)==" "
last_space<-substr(list, start = nchar(list), stop = nchar(list))==" "
Remove spaces
list[first_space]<-substr(list[first_space], start = 2, stop = nchar(list[first_space]))
list[last_space]<-substr(list[last_space], start = 1, stop = nchar(list[last_space])-1)
sql_in<-paste0(list, collapse="','")
Your output
paste0("select * from table where table.var in ",paste("('",sql_in,"')",sep=''))
"select * from table where table.var in ('first element is a space','try','this','last element is a space')"
I think You are expecting some thing like shown below code,
data <- dbGetQuery(con, "select column from yourfirsttable")
list <- paste(data$column, collapse="','")
result <- dbGetQuery(con, statement = sprintf("select * from yourresulttable where inv in ('%s')",list))
It's not entirely clear exactly what you're wanting to achieve here. For example, one use case just means you can do it all with a join. But I have cases where I don't know the values for the test without doing some computation. Then I do a separate query having created a query string thus:
> id <- 1:5
> paste0("SELECT * FROM table WHERE ID IN (", paste0(id, collapse = ","), ")")
[1] "SELECT * FROM table WHERE ID IN (1,2,3,4,5)"
As in title, there is an error in my first code in FOR loop: Command contains unrecognized phrase. I am thinking if the method string+variable is wrong.
ALTER TABLE table1 ADD COLUMN prod_n c(10)
ALTER TABLE table1 ADD COLUMN prm1 n(19,2)
ALTER TABLE table1 ADD COLUMN rbon1 n(19,2)
ALTER TABLE table1 ADD COLUMN total1 n(19,2)
There are prm2... until total5, in which the numbers represent the month.
FOR i=1 TO 5
REPLACE ALL prm+i WITH amount FOR LEFT(ALLTRIM(a),1)="P" AND
batch_mth = i
REPLACE ALL rbon+i WITH amount FOR LEFT(ALLTRIM(a),1)="R"
AND batch_mth = i
REPLACE ALL total+i WITH sum((prm+i)+(rbon+i)) FOR batch_mth = i
NEXT
ENDFOR
Thanks for the help.
There are a number of things wrong with the code you posted above. Cetin has mentioned a number of them, so I apologize if I duplicate some of them.
PROBLEM 1 - in your ALTER TABLE commands I do not see where you create fields prm2, prm3, prm4, prm5, rbon2, rbon3, etc.
And yet your FOR LOOP would be trying to write to those fields as the FOR LOOP expression i increases from 1 to 5 - if the other parts of your code was correct.
PROBLEM 2 - You cannot concatenate a String to an Integer so as to create a Field Name like you attempt to do with prm+i or rbon+1
Cetin's code suggestions would work (again as long as you had the #2, #3, etc. fields defined). However in Foxpro and Visual Foxpro you can generally do a task in a variety of ways.
Personally, for readability I'd approach your FOR LOOP like this:
FOR i=1 TO 5
* --- Keep in mind that unless fields #2, #3, #4, & #5 are defined ---
* --- The following will Fail ---
cFld1 = "prm" + STR(i,1) && define the 1st field
cFld2 = "rbon" + STR(i,1) && define the 2nd field
cFld3 = "total" + STR(i,1) && define the 3rd field
REPLACE ALL &cFld1 WITH amount ;
FOR LEFT(ALLTRIM(a),1)="P" AND batch_mth = i
REPLACE ALL &cFld2 WITH amount ;
FOR LEFT(ALLTRIM(a),1)="R" AND batch_mth = i
REPLACE ALL &cFld3 WITH sum((prm+i)+(rbon+i)) ;
FOR batch_mth = i
NEXT
NOTE - it might be good if you would learn to use VFP's Debug tools so that you can examine your code execution line-by-line in the VFP Development mode. And you can also use it to examine the variable values.
Breakpoints are good, but you have to already have the TRACE WINDOW open for the Break to work.
SET STEP ON is the Debug command that I generally use so that program execution will stop and AUTOMATICALLY open the TRACE WINDOW for looking at code execution and/or variable values.
Do you mean you have fields named prm1, prm2, prm3 ... prm12 that represent the months and you want to update them in a loop? If so, you need to understand that a "fieldName" is a "name" and thus you need to use a "name expression" to use it as a variable. That is:
prm+i
would NOT work but:
( 'pro'+ ltrim(str(m.i)) )
would.
For example here is your code revised:
For i=1 To 5
Replace All ('prm'+Ltrim(Str(m.i))) With amount For Left(Alltrim(a),1)="P" And batch_mth = m.i
Replace All ('rbon'+Ltrim(Str(m.i))) With amount For Left(Alltrim(a),1)="R" And batch_mth = m.i
* ????????? REPLACE ALL ('total'+Ltrim(Str(m.i))) WITH sum((prm+i)+(rbon+i)) FOR batch_mth = i
Endfor
However, I must admit, your code doesn't make sense to me. Maybe it would be better if you explained what you are trying to do and give some simple data with the result you expect (as code - you can use FAQ 50 on foxite to create code for data).
I have a macro where I am currently passing in 6 table names and 6 columns. However, the number of columns and tables will not always be constant.
Is there a way to have a variable number of parameters? I am familiar with the concept in python with **kwargs.
Also, is there a way to parameterize the proc sql statement to only take as many col and table inputs as provided? Or do a try catch of some sort in SAS to check if the variables exist before running the sql statement?
Here is my macro I'm trying to parameterize.
%macro Generate_TP_tbl(new_tbl_name, trans_col, tbl_1, tbl_2, tbl_3, tbl_4,
tbl_5, tbl_6, col_1, col_2, col_3, col_4, col_5, col_6);
proc sql;
CREATE TABLE &new_tbl_name AS
SELECT a1._NAME_, a1.&trans_col as &col_1, a2.&trans_col as &col_2,
a3.&trans_col as &col_3, a4.&trans_col as &col_4, a5.&trans_col as &col_5,
a6.&trans_col as &col_6
FROM &tbl_1 as a1, &tbl_2 as a2, &tbl_3 as a3, &tbl_4 as a4, &tbl_5 as a5,
&tbl_6 as a6
WHERE a1._NAME_ = a2._NAME_ = a3._NAME_ = a4._NAME_ = a5._NAME_ = a6._NAME_;
run;
%mend Generate_TP_table;
An even more generic way of doing this is as follows:
%macro mymacro /parmbuff;
%put &SYSPBUFF;
%mend;
You can then call %mymacro with any parameters you like and parse them all out from the &SYSPBUFF automatic macro variable.
This would probably need more work than Reeza's solution would, but I thought I'd post this anyway for completeness, as it's occasionally useful.
Pass them in as a single parameter and have the macro parse them out later.
%macro (parameters = , table_list = tb1 tb2 tb3 ... tb6, col_list=col1 col2 ... col6, other_parms= ... );
I would recommend building the rest of your code using a do loop with the number of parameters. The documentation here has a somewhat bad example of how to extract each element of a list:
http://support.sas.com/documentation/cdl/en/mcrolref/67912/HTML/default/viewer.htm#p1n2i0ewaj1zian1ria5579z1zjh.htm
The SQL is ugly...I wonder if a data step would be easier since you're merging on a single variable? Then it really becomes a rename from each table as in the example above in many respects.
I am just starting to learn SQL.
How do you add a condition to a statement? I am trying to sort the destination to 'BNA' which is the airport code.
SELECT
CHARTER.CUS_CODE,
CHARTER.DESTINATION "AIRPORT",
CHARTER.CHAR_DATE,
CHARTER.CHAR_DISTANCE,
CHARTER.AC_NUMBER,
FROM C.CHARTER ;
WHERE DESTINATION = 'BNA' ;
Any hints in the right direction would be great.
The following is your query with the syntax corrected:
SELECT CHARTER.CUS_CODE,
CHARTER.DESTINATION "AIRPORT",
CHARTER.CHAR_DATE,
CHARTER.CHAR_DISTANCE,
CHARTER.AC_NUMBER
FROM CHARTER
WHERE DESTINATION = 'BNA';
The semicolon goes at the end only.
Get rid of "c." from the table name in your from clause. You might have been thinking of giving it an alias of "c" which, if if that's the case, you would put it after the table name (and then use it as a prefix for each field).
SELECT
CHARTER.CUS_CODE,
CHARTER.DESTINATION "AIRPORT",
CHARTER.CHAR_DATE,
CHARTER.CHAR_DISTANCE,
CHARTER.AC_NUMBER,
FROM C.CHARTER
WHERE DESTINATION = 'BNA' ;
The ; character is a statement terminator; you only need one per SQL statement.
there is ";" at the end of the FROM statement, remove it. and try the sql again. Pay attention with the double quote too on the AIRPORT text.
SELECT CHARTER.DESTINATION + 'AIRPORT '
FROM C.CHARTER
WHERE DESTINATION = 'BNA' ;
what exactly does "%" in pass through means ? I got this code from others, the code works fine but I just don't understand why would have to put % in front of the variables. If it's a %macro I don't see any macro code in library. Any explanation would help
proc sql;
connect to odbc as d(datasrc=source);
create table out as select * from connection to d
(
select
t.id,t.rule_id,
%application_id,
t.date,
%dpv, %dpvfn1, %dpvfn2, %dpvfn3,
%AddressValid,%AddressValidMsg,%AddressType,
from &db2 t
join &db3 dxs on t.id=dxs.id
left join &db4 dxr on t.id=dxr.id
);
disconnect from d;
quit;
%MACRO X;
VAR
%MEND;
The above example is a definition of a macro.
In your question, all the columns with % are actually doing macro calls and replacing the calls with the values present in their macro definitions.For eg in ur select query...
select
t.id,t.rule_id,
%application_id,
t.date,
%dpv, %dpvfn1, %dpvfn2, %dpvfn3,
%AddressValid,%AddressValidMsg,%AddressType,
from &db2 t
join &db3 dxs on t.id=dxs.id
left join &db4 dxr on t.id=dxr.id
%application_id,%dpv, %dpvfn1, %dpvfn2, %dpvfn3,%AddressValid,%AddressValidMsg,%AddressType
All these above macro calls will retrieve their corresponding definitions and replace them in the place of your select columns...