Dynamic SQL Query in R (WHERE)
Asked Answered
B

4

6

I am trying out some dynamic SQL queries using R and the postgres package to connect to my DB.

Unfortunately I get an empty data frame if I execute the following statement:

    x <- "Mean"
query1 <- dbGetQuery(con, statement = paste(
  "SELECT *",
  "FROM name",
  "WHERE statistic = '",x,"'"))

I believe that there is a syntax error somewhere in the last line. I already changed the commas and quotation marks in every possible way, but nothing seems to work. Does anyone have an idea how I can construct this SQL Query with a dynamic WHERE Statement using a R variable?

Bust answered 2/4, 2014 at 20:29 Comment(0)
H
2

Try this:

    require(stringi)
    stri_paste("SELECT * ",
      "FROM name ",
      "WHERE statistic = '",x,"'",collapse="")
    ## [1] "SELECT * FROM name WHERE statistic = 'Mean'"

or use concatenate operator %+%

"SELECT * FROM name WHERE statistic ='" %+% x %+% "'"
## [1] "SELECT * FROM name WHERE statistic ='mean'"
Hifi answered 2/4, 2014 at 20:43 Comment(1)
The solution with the package "stringi" worked for me! Thank you!Bust
G
4

You should use paste0 instead of paste which is producing wrong results or paste(..., collapse='') which is slightly less efficient (see ?paste0 or docs here).

Also you should consider preparing your SQL statement in separated variable. In such way you can always easily check what SQL is being produced.

I would use this (and I am using this all the time):

  x   <- "Mean"
  sql <- paste0("select * from name where statistic='", x, "'")
  # print(sql)
  query1 <- dbGetQuery(con, sql)

In case I have SQL inside a function I always add debug parameter so I can see what SQL is used:

function get_statistic(x=NA, debug=FALSE) {

  sql <- paste0("select * from name where statistic='", x, "'")

  if(debug) print(sql)

  query1 <- dbGetQuery(con, sql)

  query1
}

Then I can simply use get_statistic('Mean', debug=TRUE) and I will see immediately if generated SQL is really what I expected.

Guv answered 3/4, 2014 at 7:15 Comment(0)
C
3

The Problem The problem may be that you have spaces around Mean:

x <- "Mean"
s <- paste(
  "SELECT *",
  "FROM name",
  "WHERE statistic = '",x,"'")

giving:

> s
[1] "SELECT * FROM name WHERE statistic = ' Mean '"

Corrected Version Instead try:

s <- sprintf("select * from name where statistic = '%s'", x)

giving:

> s
[1] "select * from name where statistic = 'Mean'"

gsubfn You could also try this:

library(gsubfn)
fn$dbGetQuery(con, "SELECT * 
                    FROM name 
                    WHERE statistic = '$x'")
Collyer answered 2/4, 2014 at 20:36 Comment(1)
Ah! I didnt think of that! Do you have any clue how i can delete the spaces?Bust
H
2

Try this:

    require(stringi)
    stri_paste("SELECT * ",
      "FROM name ",
      "WHERE statistic = '",x,"'",collapse="")
    ## [1] "SELECT * FROM name WHERE statistic = 'Mean'"

or use concatenate operator %+%

"SELECT * FROM name WHERE statistic ='" %+% x %+% "'"
## [1] "SELECT * FROM name WHERE statistic ='mean'"
Hifi answered 2/4, 2014 at 20:43 Comment(1)
The solution with the package "stringi" worked for me! Thank you!Bust
S
0

A newer way to do this is with the glue package, part of the tidyverse. It is described as "An implementation of interpreted string literals, inspired by Python's Literal String Interpolation."

Using glue, you would do:

library(glue)
library(DBI)
x <- "Mean"
query1 <- glue_sql("
  SELECT *
  FROM name
  WHERE statistic = ({x})
  ", .con = con)
dbGetQuery(con, query1)

It's a great package due to its flexibility. For example, let's say you wanted to import mean, median and mode statistics. Then you would add an asterisk to the call like so:

x <- c("Mean", "Median", "Mode")
query2 <- glue_sql("
  SELECT *
  FROM name
  WHERE statistic = ({x*})
  ", .con = con)
dbGetQuery(con, query2)
Subway answered 22/8, 2022 at 18:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.