Error in sqliteSendQuery(con, statement, bind.data) : error in statement: near "[ - sqldf

I need to to know why the mention error appear although when i replace DFinal[i,"x"] with any numeric value it works fine. Appreciate your help
for( i in 1:nrow(DFinal)){
+ result =0
+ var1= DFinal[i,"x"]
+ var2= DFinal[i,"y"]
+ result <- sqldf(' select count(distinct(V5)) from DLoc where V1= DFinal[i,"x"] and V5 in (select distinct(V5) from DLoc where V1=var2) ')
+
+ DFinal[i,"res"]<- result
+
+ }
Error in sqliteSendQuery(con, statement, bind.data) :
error in statement: near "[i,"x"]": syntax error

Your query doesn't make any sense, because you are referring to R variables. Instead, use the variables' values:
for (i in 1:nrow(DFinal)) {
result <- 0
var1 <- DFinal[i, "x"]
var2 <- DFinal[i, "y"]
query <- paste0('select count(distinct V5) from DLoc where V1 = ', var1,
' and V5 in (select distinct V5 from DLoc where V1 = ', var2, ')')
result <- sqldf(query)
DFinal[i, "res"] <- result
}
Your query looks like it might also need some improvement, but the above code should at least allow you to run it.
Another comment: It is generally not advisable to concatenate together a raw SQL query because it opens the possibility for a SQL injection attack. But as you are running this query in a presumably closed R environment, it might be OK as is.

Related

Condition WHERE string without/with space

I have table with some strings. I would like make select with condition string = eqauls something
I Dont have any other strings....
The select returns more rows when I Have:
What is wrong?
DECLARE #C VARCHAR(2) = 'A'+SPACE(1)
DECLARE #T TABLE (id INT NOT NULL, string VARCHAR(200) NOT NULL)
INSERT INTO #T
(
id,
string
)
VALUES
( 1, 'A'), (2,'A'+SPACE(1))
SELECT * FROM #T WHERE string = #C--With space only
Returns:
id string
1 A
2 A
I know hot to make select LIKE '%.... '.
I want to know why TSQL returns more rows.
SQL 2019, MSSQL version 18.9.2
SQL Server follows the ANSI standard when it comes to comparing strings with =. Read a longer description over here: https://dba.stackexchange.com/a/10511/7656
The bottom line is, you can't check for trailing spaces with =. Use LIKE without any % instead.
Given
CREATE TABLE T (id INT NOT NULL, string VARCHAR(200) NOT NULL)
INSERT INTO T VALUES (1, 'A')
INSERT INTO T VALUES (2, 'A ')
this
SELECT id, len(string) len, datalength(string) datalength FROM T
results in
id
len
datalength
1
1
1
2
1
2
and
SELECT id FROM T WHERE string LIKE 'A '
will give you 2. See http://sqlfiddle.com/#!18/2356c9/1
You can use one of the following solutions
-- Option 1: add to the filter the condition `DATALENGTH(#C) = DATALENGTH(string)` or 'DATALENGTH(#C) < DATALENGTH(string)'
SELECT * FROM #T WHERE string = #C and DATALENGTH(#C) <= DATALENGTH(string)
-- Option 2: Use `LIKE` and add the expresion '%'
SELECT * FROM #T WHERE string like #C + '%'
The = operator ignores trailing spaces just like LEN(). The LIKE operator does not
SELECT * FROM #T WHERE string LIKE #C
You can prove this with
SELECT CASE WHEN 'A' = 'A ' THEN 'True' ELSE 'False' END -- True
SELECT CASE WHEN 'A' = ' A' THEN 'True' ELSE 'False' END -- False because of leading space
SELECT CASE WHEN 'A' LIKE 'A ' THEN 'True' ELSE 'False' END -- False
SELECT LEN(string), FROM #T -- both return 1

Searching a substring in an string table?

I have an internal table with the following data (<fs_content>):
OFFER/005056B467AE1ED9B1962F12360477E9-A
OFFER/005056B467AE1ED9B1962F12360477E9-B
OFFER/005056B467AE1ED9B1962F12360477E9-C
OFFER/005056B467AE1ED9B1962F12360477E9-D
OFFER/005056B467AE1ED9B1962F12360477E9-E
I have to search repeatedly values like this (V1):
OFFER-A
OFFER-B
OFFER-C
OFFER-M
OFFER-L
I expect that the following values are identified, which match one line in the internal table (itab_v1_result):
OFFER-A
OFFER-B
OFFER-C
But as you can see in <fs_content> there's the same code 005056B467AE1ED9B1962F12360477E9, after OFFER/ until - symbol.
Now, I want to assign the rows from <fs_content> to field Symbol <fs_my_content> by comparing V1 value with each row in <fs_content>, but the problem is that V1 value is not completely same like <fs_content> rows.
I've tried to do something like this, but it's not working, <fs_my_content> is always empty:
READ TABLE <fs_content> ASSIGNING <fs_my_content> WITH KEY ('ATTR_NAME') = V1.
How can I get itab_v1_result to contain what I expect?
My minimal reproducible example:
TYPES:
BEGIN OF ty_content,
attr_name TYPE string,
END OF ty_content.
FIELD-SYMBOLS:
<fs_my_content> TYPE any,
<fs_content> TYPE ANY TABLE.
DATA:
itab_content TYPE STANDARD TABLE OF ty_content,
itab_v1 TYPE STANDARD TABLE OF string,
itab_v1_result TYPE STANDARD TABLE OF string,
v1 TYPE string.
itab_content = VALUE #(
( attr_name = 'OFFER/005056B467AE1ED9B1962F12360477E9-A' )
( attr_name = 'OFFER/005056B467AE1ED9B1962F12360477E9-B' )
( attr_name = 'OFFER/005056B467AE1ED9B1962F123604D7E9-C' )
( attr_name = 'OFFER/005056B467AE1ED9B1962F12360477E9-D' )
( attr_name = 'OFFER/005056B467AE1ED9B1962F12360477E9-E' ) ).
itab_v1 = VALUE #(
( `OFFER-A` )
( `OFFER-B` )
( `OFFER-C` )
( `OFFER-M` )
( `OFFER-L` ) ).
ASSIGN itab_content TO <fs_content>.
LOOP AT itab_v1 INTO v1.
READ TABLE <fs_content> ASSIGNING <fs_my_content> WITH KEY ('ATTR_NAME') = v1.
IF sy-subrc = 0.
APPEND v1 TO itab_v1_result.
ENDIF.
ENDLOOP.
" Here, itab_v1_result is empty unfortunately!?
You cannot use any operators other than = in READ TABLE. But you can use them in a LOOP.
First you'd have to arrange your V1 in a way that CS can identify, so just use the '-X', which seems to be unique. Then you can use your condition in the LOOP clause.
offset = STRLEN( v1 ) - 2.
v2 = v1+offset(2).
LOOP AT itab1 ASSIGNING <fs_itab1> WHERE attribute_name CS v2.
" do something
" if you only want to do it for the first entry you find, then just EXIT afterwards
ENDLOOP.
You are over-complicating the solution. Why not just use substring access?
LOOP AT itab_v1 INTO v1.
LOOP AT itab_content ASSIGNING FIELD-SYMBOL(<content>).
CHECK v1(5) = <content>-attr_name(5) AND substring( val = v1 off = strlen( v1 ) - 1 len = 1 ) = substring( val = <content>-attr_name off = strlen( <content>-attr_name ) - 1 len = 1 ).
APPEND v1 TO itab_v1_result.
ENDLOOP.
ENDLOOP.
Thanks a lot to all of you for your variants of solution. It was very helpful for me.
Here's the solution of my problem.
First of all we should loop at <fs_content> and assign it to new field-symbol <dynamic_content>.
Then, we should get ATTR_NAME field from <dynamic_content> and assign it to another field-symbol <contact_attribute_name>.
We'll use some function for working with STRING type value, because of this we'll assign <contact_attribute_name> to lv_attr_name.
As we know (from task description) in lv_attr_name would be the values like: OFFER/005056B467AE1ED9B1962F12360477E9-A and so on.
Because of this we'll find the position of first / by find() method from the beginning of lv_attr_name and put the value into lv_slash_position.
We repeat this operation for finding the position of first - after lv_slash_position and put the value into lv_dash_position.
After this two operation we'll use the replace() method and replace lv_dash_position - lv_slash_position to empty value. In the end we'll get OFFER/-A and put it into lv_attr_val_string.
In the end we'll compare lv_attr_val_string and v1, if lv_attr_val_string <> v1 we would not put it to the final itab itab_v1_result, else we'll do it.
LOOP AT <fs_content> ASSIGNING <dynamic_content>.
ASSIGN COMPONENT 'ATTR_NAME' OF STRUCTURE <dynamic_content> TO <contact_attribute_name>.
DATA(lv_attr_name) = CONV string( <contact_attribute_name> ).
DATA(lv_slash_position) = find( val = lv_attr_val_string
sub = '/'
off = 0 ).
IF lv_slash_position <> '1-'.
DATA(lv_dash_position) = find( val = lv_attr_val_string
sub = '-'
off = lv_slash_position ).
lv_attr_val_string = replace( val = lv_attr_val_string
off = lv_slash_position
len = ( lv_dash_position - lv_slash_position )
with = '' ).
ENDIF.
IF lv_attr_val_string <> v1.
APPEND v1 TO itab_v1_result.
CONTINUE.
ENDIF.
ENDLOOP.

Can I connect the variables In a table?

For an example, lets say I have this table:
tbl = {"hi ", "my ", "name ", "is ", "King"}
Can I get this to return:
"hi my name is King"
Without
for k, v in ipairs( tbl )
print(v)
end
Because I am trying to process an unknown quantity of inputs, and compare the result to another string.
You can use table.concat() to get the result string:
local str = table.concat(tbl)
print(str)
It can do more, in particular, table.concat() takes a second optional parameter, which can be used as the separator, for instance, to use commas to separate each elements:
local str = table.concat(tbl, ',')
The biggest advantage of table.concat() versus direct string concatenation is performance, see PiL ยง11.6 for detail.

Extract algebraic signs from string

I have a string as follows
str <- "- var_a + var_c - var_d"
and I want to change the values in a vector vec
vec <- c(var_a=0, var_b=0, var_c=0, var_d=0, var_e=0)
vec
var_a var_b var_c var_d var_e
0 0 0 0 0
according to str: whenever a variable has a negative sign, set the corresponding entry in vec to -1, if it has a positive sign to 1. My desired output would look like this:
var_a var_b var_c var_d var_e
-1 0 1 -1 0
My idea was to try to loop over all names of vec and use a regex to extract the corresoponding sign in str, but I don't really know how to get the sign, with for
instance lapply(names(vec), grepl, str) I can only see which of the variable are in the string.
Isn't there an easier way, for example with formula or expression ? I also looked at the package Ryacas but could not find what I need.
This works for your example:
splitted <- strsplit(str, " ")[[1]]
signs <- splitted[c(TRUE, FALSE)]
vars <- splitted[c(FALSE, TRUE)]
vec[vars] <- ifelse(signs == "+", 1, -1)
Would the first sign on the first variable be positive, would you have a leading + as in str <- "+ var_a + var_c - var_d"? If not, you will have to handle that separately.
Using scan to read and split data. The scan read data an put it in a vector.
vec <- c(var_a=0, var_b=0, var_c=0, var_d=0, var_e=0)
ll <- scan(text=str,what='string')
## EDIT here to treat the case the first elment is not a sign
## i.e: var_a + var_c - var_d
pos <- ll %in% c('-','+')
if(length(ll[pos]) != length(ll[!pos])) ll <- append(ll,'+',0)
vec[ll[!pos]] <- ifelse(ll[pos] == '-',-1,1)
I like the regex approach, but you have to be careful that the regex is compatible with your variable names. This splits the string on spaces that are preceeded by a letter character (you could use [[:alphanum:]] to be more flexible but I'm not sure if you would have numbers in your string...
# Split variables
args <- strsplit( str , "(?<=[a-z])\\s" , perl = TRUE )[[1]]
# Extract sign and convert to integer
sign <- as.integer( paste0( strtrim(args , 1 ) , 1 ) )
# Match and change the corresponding values of vec
vec[ match( substring( args , first = 3 ) , names(vec) ) ] <- sign
#var_a var_b var_c var_d var_e
# -1 0 1 -1 0
I was thinking of a probably slow approach along the lines of
# set up initial condition
var_a<-var_b<-var_c<-etc<-0
varnames<-c('var_a','var_b','var_c', etc)
values<-rep(0,length(varnames))
# test one by one to see what you get, w/ apologies in advance for evalparse
for (j in 1: length(varnames) ) {
assign(varnames[j],1)
values[j]<- eval(parse(str))
assign(varnames[j],0)
}
Then the values in values will tell you the sign of the variable in your string.
Ugly but fun to design :-)

Strrep not working in Matlab to make String into function

Hello I am new to MATLAB , I wanted to know how can I make my string into function . I want to access the function as a string from user in standard Matlab format (e.g exp(-10*X)-sin(pi*X)-2*tanh(X) ) Here X is the variable. Then I want to replace 'X' with 'low' and 'high' variables to calculate value of function at these limits. I have used 'strrep' for this purpose. I am getting the following errors
1)Undefined function or variable 'X'.
2) I cannot see whether 'X' was replaced with 'low' and 'high'.
Any help will be truly appreciated.
Below is my code.
high=input('Upper Limit of the Interval : ');
low=input('\nLower Limit of the interval : ');
usr_funct=input('Enter The Function in standard Matlab Format.\nEnter "X" for the
variable and * for multiply \n'); % Example exp(-10*X)-sin(pi*X)-2*tanh(X);
middle = (low+high)/2;
Flow =strrep(usr_funct, 'X', 'low');
Fhigh =strrep(usr_funct, 'X', 'high');
sprintf('Flow '); % This was to check if 'X' was replaced with 'low'. It is not printing anything
Use:
usr_funct=input('Enter The Function...', 's');
This will return the entered text as a MATLAB string, without evaluating expressions.
I think that you are looking for the eval function. That will evaluate a string as matlab code.
Here is an example:
str = 'exp(-10*X)-sin(pi*X)-2*tanh(X)' ; % let str be your math expression
high = 10; % Ask the user
low = -5; % Ask the user
% Now we evaluate for High and Low
X = low; % We want to evaluate for low
ResultLow = eval(str); % That will return your value for X = low
X = high; % We want to evaluate for low
ResultHigh = eval(str); % That will return your value for X = high
1) Undefined function or variable 'X'
If you look at the documentation for input, it says that by default, it evaluates the expression. You need to add a second argument of 's' for it to just save a string.
2) I cannot see whether 'X' was replace with 'low' and 'high'
You should type sprintf(Flow) instead of sprintf('Flow'). The latter will just output "Flow" onto the screen while the former will output the value of Flow.
Finally, the eval function may be of use later on when you actually want to evaluate your expression.

Resources